mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 01:34:27 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			189 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			189 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
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)
 | 
						|
}
 |