예제 #1
0
파일: avl.go 프로젝트: dtromb/collections
func (t *AvlTree) lookupNode(lt c.LookupType, data c.Comparable) (*avlNode, bool) {
	if t.root == nil {
		return nil, false
	}
	cn := t.root
	for {
		r := data.CompareTo(cn.data)
		if r == 0 {
			return cn, true
		}
		if r < 0 {
			if cn.l == nil {
				if lt == c.GTE {
					return cn, false
				}
				return cn.prv, false
			}
			cn = cn.l
		} else {
			if cn.r == nil {
				if lt == c.LTE {
					return cn, false
				}
				return cn.nxt, false
			}
			cn = cn.r
		}
	}
}
예제 #2
0
파일: set.go 프로젝트: dtromb/collections
func Pair(c1, c2 c.Comparable) Set {
	r := c1.CompareTo(c2)
	if r == 0 {
		return Singleton(c1)
	}
	if r < 0 {
		return &pairSet{x: c1, y: c2}
	} else {
		return &pairSet{x: c2, y: c1}
	}
}
예제 #3
0
파일: avl.go 프로젝트: dtromb/collections
// Insert adds or replaces a value in the tree.  If there is already an equal value,
// it is replaced and the old value returned.  Otherwise, nil is returned.
func (t *AvlTree) Insert(data c.Comparable) c.Comparable {
	if t.root == nil {
		t.root = &avlNode{
			data: data,
		}
		t.size++
		t.head = t.root
		t.tail = t.root
		return nil
	}
	cn := t.root
	var r int8
	for {
		r = data.CompareTo(cn.data)
		if r == 0 {
			break
		}
		if r < 0 {
			if cn.l == nil {
				break
			}
			cn = cn.l
		} else {
			if cn.r == nil {
				break
			}
			cn = cn.r
		}
	}
	if r == 0 {
		oldData := cn.data
		cn.data = data
		return oldData
	}
	nn := &avlNode{
		data: data,
		p:    cn,
	}
	if r < 0 {
		nn.prv = cn.prv
		nn.nxt = cn
		if cn.prv != nil {
			cn.prv.nxt = nn
		} else {
			t.head = nn
		}
		cn.prv = nn
		cn.l = nn
		cn.balance--
	} else {
		nn.nxt = cn.nxt
		nn.prv = cn
		if cn.nxt != nil {
			cn.nxt.prv = nn
		} else {
			t.tail = nn
		}
		cn.nxt = nn
		cn.r = nn
		cn.balance++
	}
	t.size++
	for {
		switch cn.balance {
		case 0:
			{
				// Depth did not increase, we are done.
				return nil
			}
		case -1:
			fallthrough
		case 1:
			{
				// Depth increased, propagate.
				if cn.p != nil {
					if cn.p.l == cn {
						cn.p.balance--
					} else {
						cn.p.balance++
					}
					cn = cn.p
				} else {
					return nil // At root, done.
				}
			}
		case -2:
			fallthrough
		case 2:
			{
				np, changed := t.rebalanceAtNode(cn)
				if changed {
					// Change offset the insertion height change, we're done.
					return nil
				}
				cn = np
			}
		}
	}
}