24
24
25
25
public class SampleSet <T > implements ISampleSet <T >
26
26
{
27
- private Map <T ,Node <T >> sampleMap ;
27
+ private Map <T , Node <T >> sampleMap ;
28
28
private int size ;
29
29
private long count ;
30
30
private Random random ;
@@ -51,45 +51,45 @@ public SampleSet(int capacity)
51
51
52
52
public SampleSet (int capacity , Random random )
53
53
{
54
- sampleMap = new HashMap <T ,Node <T >>(capacity );
54
+ sampleMap = new HashMap <T , Node <T >>(capacity );
55
55
this .random = random ;
56
56
}
57
57
58
58
public T peek ()
59
- {return (head != null ) ? head .element : null ;}
59
+ {
60
+ return (head != null ) ? head .element : null ;
61
+ }
60
62
61
63
public List <T > peek (int k )
62
64
{
63
65
List <T > topK = new ArrayList <T >(k );
64
- Node <T > itr = head ;
65
- int i =0 ;
66
- while (i ++<k && itr != null )
66
+ for (Node <T > itr = head ; itr != null && topK .size () < k ; itr = itr .next )
67
67
{
68
68
topK .add (itr .element );
69
- itr = itr .next ;
70
- }
69
+ }
71
70
return topK ;
72
71
}
73
72
74
73
public long put (T element )
75
74
{
76
75
Node <T > node = sampleMap .get (element );
77
- if (node != null )
76
+ if (node != null )
78
77
{
79
78
node .count ++;
80
79
promote (node );
81
80
}
82
81
else
83
82
{
84
- node = new Node <T >(element );
83
+ node = new Node <T >();
84
+ node .element = element ;
85
85
node .count = 1 ;
86
86
node .prev = tail ;
87
- if (tail != null )
87
+ if (tail != null )
88
88
{
89
89
tail .next = node ;
90
90
}
91
91
tail = node ;
92
- if (head == null )
92
+ if (head == null )
93
93
{
94
94
head = node ;
95
95
}
@@ -103,123 +103,106 @@ public long put(T element)
103
103
public T removeRandom ()
104
104
{
105
105
double p = random .nextDouble ();
106
- Node <T > itr = head ;
107
106
long weight = 0 ;
108
- while ( itr != null )
107
+ for ( Node < T > itr = head ; itr != null ; itr = itr . next )
109
108
{
110
109
weight += itr .count ;
111
- if (p < weight /(double )count )
112
- {
113
- break ;
114
- }
115
- itr = itr .next ;
116
- }
117
-
118
- T removed = null ;
119
- if (itr != null )
120
- {
121
- removed = itr .element ;
122
- itr .count --;
123
- count --;
124
- demote (itr );
125
- if (itr .count == 0 )
110
+ if (p < weight / (double ) count )
126
111
{
127
- removeMin ();
112
+ itr .count --;
113
+ count --;
114
+ demote (itr );
115
+ if (itr .count == 0 )
116
+ {
117
+ removeMin ();
118
+ }
119
+ return itr .element ;
128
120
}
129
121
}
130
-
131
- return removed ;
122
+ return null ;
132
123
}
133
124
134
125
protected T removeMin ()
135
126
{
136
- T minElement = null ;
137
- if (tail != null )
127
+ if (tail == null )
138
128
{
139
- size -- ;
140
- count -= tail . count ;
141
- minElement = tail . element ;
142
- tail = tail .prev ;
143
- if ( tail != null )
144
- {
145
- tail . next = null ;
146
- }
147
- sampleMap . remove ( minElement ) ;
129
+ return null ;
130
+ }
131
+ size -- ;
132
+ count - = tail .count ;
133
+ T minElement = tail . element ;
134
+ tail = tail . prev ;
135
+ if ( tail ! = null )
136
+ {
137
+ tail . next = null ;
148
138
}
139
+ sampleMap .remove (minElement );
149
140
return minElement ;
150
141
}
151
142
152
143
public int size ()
153
- {return size ;}
144
+ {
145
+ return size ;
146
+ }
154
147
155
148
public long count ()
156
- {return count ;}
149
+ {
150
+ return count ;
151
+ }
157
152
158
153
protected T peekMin ()
159
- {return tail .element ;}
154
+ {
155
+ return tail .element ;
156
+ }
160
157
161
- protected int promote (Node <T > node )
158
+ protected void promote (Node <T > node )
162
159
{
163
- int promotion = 0 ;
164
- while (node .prev != null && node .count > node .prev .count )
160
+ // Bring node closer to the head as necessary
161
+ while (node .prev != null && node .count > node .prev .count )
165
162
{
166
- node .prev .next = node .next ;
167
- node .next = node .prev ;
168
- node .prev = node .next .prev ;
169
- node .next .prev = node ;
170
- if (node .prev != null )
171
- {
172
- node .prev .next = node ;
173
- }
174
- else
175
- {
176
- head = node ;
177
- }
178
- if (node .next .next != null )
179
- {
180
- node .next .next .prev = node .next ;
181
- }
182
- else
183
- {
184
- tail = node .next ;
185
- }
163
+ // BEFORE head... [A]node.prev.prev --> [B]node.prev --> [C]node --> [D]node.next ...tail
164
+ // AFTER head... [A]node.prev.prev --> [C]node --> [B]node.prev --> [D]node.next ...tail
165
+ Node <T > b = node .prev , c = node , d = node .next , a = (b == null ) ? null : b .prev ;
166
+
167
+ // Re-link each of 3 neighboring pairs
168
+ if (a != null ) a .next = c ;
169
+ c .prev = a ;
170
+
171
+ c .next = b ;
172
+ b .prev = c ;
186
173
187
- promotion ++;
174
+ b .next = d ;
175
+ if (d != null ) d .prev = b ;
176
+
177
+ // B and C may have switched head/tail roles
178
+ if (head == b ) head = c ;
179
+ if (tail == c ) tail = b ;
188
180
}
189
- return promotion ;
190
181
}
191
182
192
- protected int demote (Node <T > node )
183
+ protected void demote (Node <T > node )
193
184
{
194
- int demotion = 0 ;
195
-
196
- while (node .next != null && node .count < node .next .count )
185
+ // Bring node closer to the tail as necessary
186
+ while (node .next != null && node .count < node .next .count )
197
187
{
198
- node .next .prev = node .prev ;
199
- node .prev = node .next ;
200
- node .next = node .prev .next ;
201
- node .prev .next = node ;
202
- if (node .next != null )
203
- {
204
- node .next .prev = node ;
205
- }
206
- else
207
- {
208
- tail = node ;
209
- }
210
- if (node .prev .prev != null )
211
- {
212
- node .prev .prev .next = node .prev ;
213
- }
214
- else
215
- {
216
- head = node .prev ;
217
- }
188
+ // BEFORE head... [A]node.prev --> [B]node --> [C]node.next --> [D]node.next.next ...tail
189
+ // AFTER head... [A]node.prev --> [C]node.next --> [B]node --> [D]node.next.next ...tail
190
+ Node <T > a = node .prev , b = node , c = node .next , d = (c == null ) ? null : c .next ;
218
191
219
- demotion ++;
220
- }
192
+ // Re-link each of 3 neighboring pairs
193
+ if (a != null ) a .next = c ;
194
+ c .prev = a ;
195
+
196
+ c .next = b ;
197
+ b .prev = c ;
221
198
222
- return demotion ;
199
+ if (d != null ) d .prev = b ;
200
+ b .next = d ;
201
+
202
+ // B and C may have switched head/tail roles
203
+ if (head == b ) head = c ;
204
+ if (tail == c ) tail = b ;
205
+ }
223
206
}
224
207
225
208
private class Node <E >
@@ -228,11 +211,5 @@ private class Node<E>
228
211
private Node <E > prev ;
229
212
private E element ;
230
213
private long count ;
231
-
232
- public Node (E element )
233
- {
234
- this .element = element ;
235
- }
236
214
}
237
-
238
215
}
0 commit comments