Chromium Code Reviews| 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 |