Add treap ascending Iterators.

Add ascending iterators. An Iterator retains a reference to a Treap and
returns successive values. It functions identically to VisitItemsAscend,
save that it retains its iteration state and can be invoked iteratively.
diff --git a/treap.go b/treap.go
index f758ffe..0cb8160 100644
--- a/treap.go
+++ b/treap.go
@@ -167,6 +167,12 @@
 
 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 @@
 	}
 	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
+}
diff --git a/treap_test.go b/treap_test.go
index 4ed0973..21e0e7c 100644
--- a/treap_test.go
+++ b/treap_test.go
@@ -96,9 +96,11 @@
 	return x
 }
 
-func visitExpect(t *testing.T, x *Treap, start string, arr []string) {
+type treapVisitor func(x *Treap, pivot Item, visitor ItemVisitor)
+
+func visitExpect(t *testing.T, x *Treap, v treapVisitor, start string, arr []string) {
 	n := 0
-	x.VisitAscend(start, func(i Item) bool {
+	v(x, start, func(i Item) bool {
 		if i.(string) != arr[n] {
 			t.Errorf("expected visit item: %v, saw: %v", arr[n], i)
 		}
@@ -107,26 +109,27 @@
 	})
 	if n != len(arr) {
 		t.Errorf("expected # visit callbacks: %v, saw: %v", len(arr), n)
+		panic(nil)
 	}
 }
 
-func TestVisit(t *testing.T) {
+func testVisitImpl(t *testing.T, fn treapVisitor) {
 	x := NewTreap(stringCompare)
-	visitExpect(t, x, "a", []string{})
+	visitExpect(t, x, fn, "a", []string{})
 
 	x = load(x, []string{"e", "d", "c", "c", "a", "b", "a"})
 
 	visitX := func() {
-		visitExpect(t, x, "a", []string{"a", "b", "c", "d", "e"})
-		visitExpect(t, x, "a1", []string{"b", "c", "d", "e"})
-		visitExpect(t, x, "b", []string{"b", "c", "d", "e"})
-		visitExpect(t, x, "b1", []string{"c", "d", "e"})
-		visitExpect(t, x, "c", []string{"c", "d", "e"})
-		visitExpect(t, x, "c1", []string{"d", "e"})
-		visitExpect(t, x, "d", []string{"d", "e"})
-		visitExpect(t, x, "d1", []string{"e"})
-		visitExpect(t, x, "e", []string{"e"})
-		visitExpect(t, x, "f", []string{})
+		visitExpect(t, x, fn, "a", []string{"a", "b", "c", "d", "e"})
+		visitExpect(t, x, fn, "a1", []string{"b", "c", "d", "e"})
+		visitExpect(t, x, fn, "b", []string{"b", "c", "d", "e"})
+		visitExpect(t, x, fn, "b1", []string{"c", "d", "e"})
+		visitExpect(t, x, fn, "c", []string{"c", "d", "e"})
+		visitExpect(t, x, fn, "c1", []string{"d", "e"})
+		visitExpect(t, x, fn, "d", []string{"d", "e"})
+		visitExpect(t, x, fn, "d1", []string{"e"})
+		visitExpect(t, x, fn, "e", []string{"e"})
+		visitExpect(t, x, fn, "f", []string{})
 	}
 	visitX()
 
@@ -136,17 +139,17 @@
 	y = y.Upsert("cc", 2)
 	y = y.Delete("c")
 
-	visitExpect(t, y, "a", []string{"b", "cc", "d", "e", "f"})
-	visitExpect(t, y, "a1", []string{"b", "cc", "d", "e", "f"})
-	visitExpect(t, y, "b", []string{"b", "cc", "d", "e", "f"})
-	visitExpect(t, y, "b1", []string{"cc", "d", "e", "f"})
-	visitExpect(t, y, "c", []string{"cc", "d", "e", "f"})
-	visitExpect(t, y, "c1", []string{"cc", "d", "e", "f"})
-	visitExpect(t, y, "d", []string{"d", "e", "f"})
-	visitExpect(t, y, "d1", []string{"e", "f"})
-	visitExpect(t, y, "e", []string{"e", "f"})
-	visitExpect(t, y, "f", []string{"f"})
-	visitExpect(t, y, "z", []string{})
+	visitExpect(t, y, fn, "a", []string{"b", "cc", "d", "e", "f"})
+	visitExpect(t, y, fn, "a1", []string{"b", "cc", "d", "e", "f"})
+	visitExpect(t, y, fn, "b", []string{"b", "cc", "d", "e", "f"})
+	visitExpect(t, y, fn, "b1", []string{"cc", "d", "e", "f"})
+	visitExpect(t, y, fn, "c", []string{"cc", "d", "e", "f"})
+	visitExpect(t, y, fn, "c1", []string{"cc", "d", "e", "f"})
+	visitExpect(t, y, fn, "d", []string{"d", "e", "f"})
+	visitExpect(t, y, fn, "d1", []string{"e", "f"})
+	visitExpect(t, y, fn, "e", []string{"e", "f"})
+	visitExpect(t, y, fn, "f", []string{"f"})
+	visitExpect(t, y, fn, "z", []string{})
 
 	// an uninitialized treap
 	z := NewTreap(stringCompare)
@@ -185,7 +188,25 @@
 	}
 }
 
-func visitExpectEndAtC(t *testing.T, x *Treap, start string, arr []string) {
+func TestVisit(t *testing.T) {
+	testVisitImpl(t, func(x *Treap, pivot Item, visitor ItemVisitor) {
+		x.VisitAscend(pivot, visitor)
+	})
+}
+
+func TestVisitIter(t *testing.T) {
+	testVisitImpl(t, func(x *Treap, pivot Item, visitor ItemVisitor) {
+		it := x.Iterator(pivot)
+		for {
+			i, ok := it.Next()
+			if !ok || !visitor(i) {
+				return
+			}
+		}
+	})
+}
+
+func visitExpectEndAtC(t *testing.T, x *Treap, fn treapVisitor, start string, arr []string) {
 	n := 0
 	x.VisitAscend(start, func(i Item) bool {
 		if stringCompare(i, "c") > 0 {
@@ -202,27 +223,45 @@
 	}
 }
 
-func TestVisitEndEarly(t *testing.T) {
+func testVisitEndEarlyImpl(t *testing.T, fn treapVisitor) {
 	x := NewTreap(stringCompare)
-	visitExpectEndAtC(t, x, "a", []string{})
+	visitExpectEndAtC(t, x, fn, "a", []string{})
 
 	x = load(x, []string{"e", "d", "c", "c", "a", "b", "a", "e"})
 
 	visitX := func() {
-		visitExpectEndAtC(t, x, "a", []string{"a", "b", "c"})
-		visitExpectEndAtC(t, x, "a1", []string{"b", "c"})
-		visitExpectEndAtC(t, x, "b", []string{"b", "c"})
-		visitExpectEndAtC(t, x, "b1", []string{"c"})
-		visitExpectEndAtC(t, x, "c", []string{"c"})
-		visitExpectEndAtC(t, x, "c1", []string{})
-		visitExpectEndAtC(t, x, "d", []string{})
-		visitExpectEndAtC(t, x, "d1", []string{})
-		visitExpectEndAtC(t, x, "e", []string{})
-		visitExpectEndAtC(t, x, "f", []string{})
+		visitExpectEndAtC(t, x, fn, "a", []string{"a", "b", "c"})
+		visitExpectEndAtC(t, x, fn, "a1", []string{"b", "c"})
+		visitExpectEndAtC(t, x, fn, "b", []string{"b", "c"})
+		visitExpectEndAtC(t, x, fn, "b1", []string{"c"})
+		visitExpectEndAtC(t, x, fn, "c", []string{"c"})
+		visitExpectEndAtC(t, x, fn, "c1", []string{})
+		visitExpectEndAtC(t, x, fn, "d", []string{})
+		visitExpectEndAtC(t, x, fn, "d1", []string{})
+		visitExpectEndAtC(t, x, fn, "e", []string{})
+		visitExpectEndAtC(t, x, fn, "f", []string{})
 	}
 	visitX()
 }
 
+func TestVisitEndEarly(t *testing.T) {
+	testVisitEndEarlyImpl(t, func(x *Treap, pivot Item, visitor ItemVisitor) {
+		x.VisitAscend(pivot, visitor)
+	})
+}
+
+func TestVisitEndEarlyIter(t *testing.T) {
+	testVisitEndEarlyImpl(t, func(x *Treap, pivot Item, visitor ItemVisitor) {
+		it := x.Iterator(pivot)
+		for {
+			i, ok := it.Next()
+			if !ok || !visitor(i) {
+				return
+			}
+		}
+	})
+}
+
 func TestPriorityAfterUpsert(t *testing.T) {
 	// See https://github.com/steveyen/gtreap/issues/3 found by icexin.