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

Side by Side Diff: treap.go

Issue 2604933002: Add treap ascending Iterators. (Closed)
Patch Set: Created 3 years, 11 months 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 unified diff | Download patch
« no previous file with comments | « no previous file | treap_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 }
OLDNEW
« 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