mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-31 14:31:02 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			188 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			188 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package gtreap
 | |
| 
 | |
| type Treap struct {
 | |
| 	compare Compare
 | |
| 	root    *node
 | |
| }
 | |
| 
 | |
| // Compare returns an integer comparing the two items
 | |
| // lexicographically. The result will be 0 if a==b, -1 if a < b, and
 | |
| // +1 if a > b.
 | |
| type Compare func(a, b interface{}) int
 | |
| 
 | |
| // Item can be anything.
 | |
| type Item interface{}
 | |
| 
 | |
| type node struct {
 | |
| 	item     Item
 | |
| 	priority int
 | |
| 	left     *node
 | |
| 	right    *node
 | |
| }
 | |
| 
 | |
| func NewTreap(c Compare) *Treap {
 | |
| 	return &Treap{compare: c, root: nil}
 | |
| }
 | |
| 
 | |
| func (t *Treap) Min() Item {
 | |
| 	n := t.root
 | |
| 	if n == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	for n.left != nil {
 | |
| 		n = n.left
 | |
| 	}
 | |
| 	return n.item
 | |
| }
 | |
| 
 | |
| func (t *Treap) Max() Item {
 | |
| 	n := t.root
 | |
| 	if n == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	for n.right != nil {
 | |
| 		n = n.right
 | |
| 	}
 | |
| 	return n.item
 | |
| }
 | |
| 
 | |
| func (t *Treap) Get(target Item) Item {
 | |
| 	n := t.root
 | |
| 	for n != nil {
 | |
| 		c := t.compare(target, n.item)
 | |
| 		if c < 0 {
 | |
| 			n = n.left
 | |
| 		} else if c > 0 {
 | |
| 			n = n.right
 | |
| 		} else {
 | |
| 			return n.item
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Note: only the priority of the first insert of an item is used.
 | |
| // Priorities from future updates on already existing items are
 | |
| // ignored.  To change the priority for an item, you need to do a
 | |
| // Delete then an Upsert.
 | |
| func (t *Treap) Upsert(item Item, itemPriority int) *Treap {
 | |
| 	r := t.union(t.root, &node{item: item, priority: itemPriority})
 | |
| 	return &Treap{compare: t.compare, root: r}
 | |
| }
 | |
| 
 | |
| func (t *Treap) union(this *node, that *node) *node {
 | |
| 	if this == nil {
 | |
| 		return that
 | |
| 	}
 | |
| 	if that == nil {
 | |
| 		return this
 | |
| 	}
 | |
| 	if this.priority > that.priority {
 | |
| 		left, middle, right := t.split(that, this.item)
 | |
| 		if middle == nil {
 | |
| 			return &node{
 | |
| 				item:     this.item,
 | |
| 				priority: this.priority,
 | |
| 				left:     t.union(this.left, left),
 | |
| 				right:    t.union(this.right, right),
 | |
| 			}
 | |
| 		}
 | |
| 		return &node{
 | |
| 			item:     middle.item,
 | |
| 			priority: this.priority,
 | |
| 			left:     t.union(this.left, left),
 | |
| 			right:    t.union(this.right, right),
 | |
| 		}
 | |
| 	}
 | |
| 	// We don't use middle because the "that" has precendence.
 | |
| 	left, _, right := t.split(this, that.item)
 | |
| 	return &node{
 | |
| 		item:     that.item,
 | |
| 		priority: that.priority,
 | |
| 		left:     t.union(left, that.left),
 | |
| 		right:    t.union(right, that.right),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Splits a treap into two treaps based on a split item "s".
 | |
| // The result tuple-3 means (left, X, right), where X is either...
 | |
| // nil - meaning the item s was not in the original treap.
 | |
| // non-nil - returning the node that had item s.
 | |
| // The tuple-3's left result treap has items < s,
 | |
| // and the tuple-3's right result treap has items > s.
 | |
| func (t *Treap) split(n *node, s Item) (*node, *node, *node) {
 | |
| 	if n == nil {
 | |
| 		return nil, nil, nil
 | |
| 	}
 | |
| 	c := t.compare(s, n.item)
 | |
| 	if c == 0 {
 | |
| 		return n.left, n, n.right
 | |
| 	}
 | |
| 	if c < 0 {
 | |
| 		left, middle, right := t.split(n.left, s)
 | |
| 		return left, middle, &node{
 | |
| 			item:     n.item,
 | |
| 			priority: n.priority,
 | |
| 			left:     right,
 | |
| 			right:    n.right,
 | |
| 		}
 | |
| 	}
 | |
| 	left, middle, right := t.split(n.right, s)
 | |
| 	return &node{
 | |
| 		item:     n.item,
 | |
| 		priority: n.priority,
 | |
| 		left:     n.left,
 | |
| 		right:    left,
 | |
| 	}, middle, right
 | |
| }
 | |
| 
 | |
| func (t *Treap) Delete(target Item) *Treap {
 | |
| 	left, _, right := t.split(t.root, target)
 | |
| 	return &Treap{compare: t.compare, root: t.join(left, right)}
 | |
| }
 | |
| 
 | |
| // All the items from this are < items from that.
 | |
| func (t *Treap) join(this *node, that *node) *node {
 | |
| 	if this == nil {
 | |
| 		return that
 | |
| 	}
 | |
| 	if that == nil {
 | |
| 		return this
 | |
| 	}
 | |
| 	if this.priority > that.priority {
 | |
| 		return &node{
 | |
| 			item:     this.item,
 | |
| 			priority: this.priority,
 | |
| 			left:     this.left,
 | |
| 			right:    t.join(this.right, that),
 | |
| 		}
 | |
| 	}
 | |
| 	return &node{
 | |
| 		item:     that.item,
 | |
| 		priority: that.priority,
 | |
| 		left:     t.join(this, that.left),
 | |
| 		right:    that.right,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type ItemVisitor func(i Item) bool
 | |
| 
 | |
| // Visit items greater-than-or-equal to the pivot.
 | |
| func (t *Treap) VisitAscend(pivot Item, visitor ItemVisitor) {
 | |
| 	t.visitAscend(t.root, pivot, visitor)
 | |
| }
 | |
| 
 | |
| func (t *Treap) visitAscend(n *node, pivot Item, visitor ItemVisitor) bool {
 | |
| 	if n == nil {
 | |
| 		return true
 | |
| 	}
 | |
| 	if t.compare(pivot, n.item) <= 0 {
 | |
| 		if !t.visitAscend(n.left, pivot, visitor) {
 | |
| 			return false
 | |
| 		}
 | |
| 		if !visitor(n.item) {
 | |
| 			return false
 | |
| 		}
 | |
| 	}
 | |
| 	return t.visitAscend(n.right, pivot, visitor)
 | |
| }
 |