Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(635)

Unified Diff: treap.go

Issue 2604933002: Add treap ascending Iterators. (Closed)
Patch Set: Avoid stack for nil left node case. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | treap_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: treap.go
diff --git a/treap.go b/treap.go
index f758ffe444b427616e5b32668e3361f649d4a937..0cb8160cb0384884cef1c8c2d1803a8b1c9bca23 100644
--- a/treap.go
+++ b/treap.go
@@ -167,6 +167,12 @@ func (t *Treap) join(this *node, that *node) *node {
type ItemVisitor func(i Item) bool
+// Iterator returns an ascending Iterator instance that is bound to this Treap.
+// The iterator begins at "pivot" and iterates through the end of the Treap.
+func (t *Treap) Iterator(pivot Item) *Iterator {
+ return newIterator(t, pivot)
+}
+
// Visit items greater-than-or-equal to the pivot.
func (t *Treap) VisitAscend(pivot Item, visitor ItemVisitor) {
t.visitAscend(t.root, pivot, visitor)
@@ -186,3 +192,78 @@ func (t *Treap) visitAscend(n *node, pivot Item, visitor ItemVisitor) bool {
}
return t.visitAscend(n.right, pivot, visitor)
}
+
+// Iterator supports iterative ascending traversal of the Treap. An Iterator is
+// instantiated by calling a Treap's Iterator method.
+type Iterator struct {
+ t *Treap
+ pivot Item
+ stack []stackNode
+}
+
+type stackNode struct {
+ n *node
+ visited bool
+}
+
+func newIterator(t *Treap, pivot Item) *Iterator {
+ it := Iterator{t: t, pivot: pivot}
+ it.pushStack(t.root, false)
+ return &it
+}
+
+// Next returns the next Item in the iteration sequence.
+//
+// If another item exists in the iteration sequence, true will be returned as
+// the second return value; if not, false will be returned, indicating end of
+// iteration. Additional calls to Next after end of iteration will continue
+// to return false.
+func (it *Iterator) Next() (Item, bool) {
+ for {
+ n, visited := it.popStack()
+ if n == nil {
+ return nil, false
+ }
+
+ if visited {
+ // Only nodes that have already satisfied comparison will be placed on
+ // the stack as "visited", so we can safely process them without
+ // performing the comparison again.
+ return n.item, true
+ }
+
+ if n.right != nil {
+ it.pushStack(n.right, false)
+ }
+ if it.t.compare(it.pivot, n.item) <= 0 {
+ // Visit our left node first. We will push "n" back onto the stack and
+ // mark it visited so we don't revisit its children.
+ if n.left == nil {
+ // No left node, so we will skip the stack and visit "n" this round.
+ return n.item, true
+ }
+
+ // Process "n" after its left child. Mark it "visited" so we don't re-push
+ // entries onto the stack or re-compare.
+ it.pushStack(n, true)
+ it.pushStack(n.left, false)
+ }
+ }
+}
+
+func (it *Iterator) pushStack(n *node, visited bool) {
+ it.stack = append(it.stack, stackNode{n, visited})
+}
+
+func (it *Iterator) popStack() (n *node, visited bool) {
+ end := len(it.stack) - 1
+ if end < 0 {
+ return nil, false
+ }
+
+ sn := &it.stack[end]
+ n, visited = sn.n, sn.visited
+ sn.n = nil // Clear the node reference from our stack.
+ it.stack = it.stack[:end]
+ return
+}
« no previous file with comments | « no previous file | treap_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698