OLD | NEW |
---|---|
1 package gtreap | 1 package gtreap |
2 | 2 |
3 type Treap struct { | 3 type Treap struct { |
4 compare Compare | 4 compare Compare |
5 root *node | 5 root *node |
6 } | 6 } |
7 | 7 |
8 // Compare returns an integer comparing the two items | 8 // Compare returns an integer comparing the two items |
9 // lexicographically. The result will be 0 if a==b, -1 if a < b, and | 9 // lexicographically. The result will be 0 if a==b, -1 if a < b, and |
10 // +1 if a > b. | 10 // +1 if a > b. |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
160 return &node{ | 160 return &node{ |
161 item: that.item, | 161 item: that.item, |
162 priority: that.priority, | 162 priority: that.priority, |
163 left: t.join(this, that.left), | 163 left: t.join(this, that.left), |
164 right: that.right, | 164 right: that.right, |
165 } | 165 } |
166 } | 166 } |
167 | 167 |
168 type ItemVisitor func(i Item) bool | 168 type ItemVisitor func(i Item) bool |
169 | 169 |
170 // Iterator returns an ascending Iterator instance that is bound to this Treap. | |
171 // The iterator begins at "pivot" and iterates through the end of the Treap. | |
172 func (t *Treap) Iterator(pivot Item) *Iterator { | |
173 return newIterator(t, pivot) | |
174 } | |
175 | |
170 // Visit items greater-than-or-equal to the pivot. | 176 // Visit items greater-than-or-equal to the pivot. |
171 func (t *Treap) VisitAscend(pivot Item, visitor ItemVisitor) { | 177 func (t *Treap) VisitAscend(pivot Item, visitor ItemVisitor) { |
172 t.visitAscend(t.root, pivot, visitor) | 178 t.visitAscend(t.root, pivot, visitor) |
173 } | 179 } |
174 | 180 |
175 func (t *Treap) visitAscend(n *node, pivot Item, visitor ItemVisitor) bool { | 181 func (t *Treap) visitAscend(n *node, pivot Item, visitor ItemVisitor) bool { |
176 if n == nil { | 182 if n == nil { |
177 return true | 183 return true |
178 } | 184 } |
179 if t.compare(pivot, n.item) <= 0 { | 185 if t.compare(pivot, n.item) <= 0 { |
180 if !t.visitAscend(n.left, pivot, visitor) { | 186 if !t.visitAscend(n.left, pivot, visitor) { |
181 return false | 187 return false |
182 } | 188 } |
183 if !visitor(n.item) { | 189 if !visitor(n.item) { |
184 return false | 190 return false |
185 } | 191 } |
186 } | 192 } |
187 return t.visitAscend(n.right, pivot, visitor) | 193 return t.visitAscend(n.right, pivot, visitor) |
188 } | 194 } |
195 | |
196 // Iterator supports iterative ascending traversal of the Treap. An Iterator is | |
197 // instantiated by calling a Treap's Iterator method. | |
198 type Iterator struct { | |
199 t *Treap | |
200 pivot Item | |
201 stack []stackNode | |
202 } | |
203 | |
204 type stackNode struct { | |
205 n *node | |
206 visited bool | |
207 } | |
208 | |
209 func newIterator(t *Treap, pivot Item) *Iterator { | |
210 it := Iterator{t: t, pivot: pivot} | |
211 it.pushStack(t.root, false) | |
212 return &it | |
213 } | |
214 | |
215 // Next returns the next Item in the iteration sequence. | |
216 // | |
217 // If another item exists in the iteration sequence, true will be returned as | |
218 // the second return value; if not, false will be returned, indicating end of | |
219 // iteration. Additional calls to Next after end of iteration will continue | |
220 // to return false. | |
221 func (it *Iterator) Next() (Item, bool) { | |
Vadim Sh.
2016/12/28 01:44:14
this can totally be implemented as a goroutine and
dnj
2016/12/28 02:40:03
The thing that really turned me off from that is t
| |
222 for { | |
223 n, visited := it.popStack() | |
224 if n == nil { | |
225 return nil, false | |
226 } | |
227 | |
228 if visited { | |
229 // Only nodes that have already satisfied comparison wil l be placed on | |
230 // the stack as "visited", so we can safely process them without | |
231 // performing the comparison again. | |
232 return n.item, true | |
233 } | |
234 | |
235 if n.right != nil { | |
236 it.pushStack(n.right, false) | |
237 } | |
238 if it.t.compare(it.pivot, n.item) <= 0 { | |
239 // Visit our left node first. We will push "n" back onto the stack and | |
240 // mark it visited so we don't revisit its children. | |
241 it.pushStack(n, true) | |
242 | |
243 if n.left != nil { | |
244 it.pushStack(n.left, false) | |
245 } | |
246 } | |
247 } | |
248 } | |
249 | |
250 func (it *Iterator) pushStack(n *node, visited bool) { | |
251 it.stack = append(it.stack, stackNode{n, visited}) | |
252 } | |
253 | |
254 func (it *Iterator) popStack() (n *node, visited bool) { | |
255 end := len(it.stack) - 1 | |
256 if end < 0 { | |
257 return nil, false | |
258 } | |
259 | |
260 sn := &it.stack[end] | |
261 n, visited = sn.n, sn.visited | |
262 sn.n = nil // Clear the node reference from our stack. | |
263 it.stack = it.stack[:end] | |
264 return | |
265 } | |
OLD | NEW |