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) { |
| 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 if n.left == nil { |
| 242 // No left node, so we will skip the stack and v
isit "n" this round. |
| 243 return n.item, true |
| 244 } |
| 245 |
| 246 // Process "n" after its left child. Mark it "visited" s
o we don't re-push |
| 247 // entries onto the stack or re-compare. |
| 248 it.pushStack(n, true) |
| 249 it.pushStack(n.left, false) |
| 250 } |
| 251 } |
| 252 } |
| 253 |
| 254 func (it *Iterator) pushStack(n *node, visited bool) { |
| 255 it.stack = append(it.stack, stackNode{n, visited}) |
| 256 } |
| 257 |
| 258 func (it *Iterator) popStack() (n *node, visited bool) { |
| 259 end := len(it.stack) - 1 |
| 260 if end < 0 { |
| 261 return nil, false |
| 262 } |
| 263 |
| 264 sn := &it.stack[end] |
| 265 n, visited = sn.n, sn.visited |
| 266 sn.n = nil // Clear the node reference from our stack. |
| 267 it.stack = it.stack[:end] |
| 268 return |
| 269 } |
OLD | NEW |