package splay import ( "fmt" ) type ( Any interface{} LessFunc func(interface{}, interface{}) bool VisitFunc func(interface{}) bool node struct { value Any parent, left, right *node } nodei struct { step int node *node prev *nodei } SplayTree struct { length int root *node less LessFunc } ) // Create a new splay tree, using the less function to determine the order. func New(less LessFunc) *SplayTree { return &SplayTree{0, nil, less} } // Get the first value from the collection. Returns nil if empty. func (this *SplayTree) First() Any { if this.length == 0 { return nil } n := this.root for n.left != nil { n = n.left } return n.value } // Get the last value from the collection. Returns nil if empty. func (this *SplayTree) Last() Any { if this.length == 0 { return nil } n := this.root for n.right != nil { n = n.right } return n.value } // Get an item from the splay tree func (this *SplayTree) Get(item Any) Any { if this.length == 0 { return nil } n := this.root for n != nil { if this.less(item, n.value) { n = n.left continue } if this.less(n.value, item) { n = n.right continue } this.splay(n) return n.value } return nil } func (this *SplayTree) Has(value Any) bool { return this.Get(value) != nil } func (this *SplayTree) Init() { this.length = 0 this.root = nil } func (this *SplayTree) Add(value Any) { if this.length == 0 { this.root = &node{value, nil, nil, nil} this.length = 1 return } n := this.root for { if this.less(value, n.value) { if n.left == nil { n.left = &node{value, n, nil, nil} this.length++ n = n.left break } n = n.left continue } if this.less(n.value, value) { if n.right == nil { n.right = &node{value, n, nil, nil} this.length++ n = n.right break } n = n.right continue } n.value = value break } this.splay(n) } func (this *SplayTree) PreOrder(visit VisitFunc) { if this.length == 1 { return } i := &nodei{0, this.root, nil} for i != nil { switch i.step { // Value case 0: i.step++ if !visit(i.node.value) { break } // Left case 1: i.step++ if i.node.left != nil { i = &nodei{0, i.node.left, i} } // Right case 2: i.step++ if i.node.right != nil { i = &nodei{0, i.node.right, i} } default: i = i.prev } } } func (this *SplayTree) InOrder(visit VisitFunc) { if this.length == 1 { return } i := &nodei{0, this.root, nil} for i != nil { switch i.step { // Left case 0: i.step++ if i.node.left != nil { i = &nodei{0, i.node.left, i} } // Value case 1: i.step++ if !visit(i.node.value) { break } // Right case 2: i.step++ if i.node.right != nil { i = &nodei{0, i.node.right, i} } default: i = i.prev } } } func (this *SplayTree) PostOrder(visit VisitFunc) { if this.length == 1 { return } i := &nodei{0, this.root, nil} for i != nil { switch i.step { // Left case 0: i.step++ if i.node.left != nil { i = &nodei{0, i.node.left, i} } // Right case 1: i.step++ if i.node.right != nil { i = &nodei{0, i.node.right, i} } // Value case 2: i.step++ if !visit(i.node.value) { break } default: i = i.prev } } } func (this *SplayTree) Do(visit VisitFunc) { this.InOrder(visit) } func (this *SplayTree) Len() int { return this.length } func (this *SplayTree) Remove(value Any) { if this.length == 0 { return } n := this.root for n != nil { if this.less(value, n.value) { n = n.left continue } if this.less(n.value, value) { n = n.right continue } // First splay the parent node if n.parent != nil { this.splay(n.parent) } // No children if n.left == nil && n.right == nil { // guess we're the root node if n.parent == nil { this.root = nil break } if n.parent.left == n { n.parent.left = nil } else { n.parent.right = nil } } else if n.left == nil { // root node if n.parent == nil { this.root = n.right break } if n.parent.left == n { n.parent.left = n.right } else { n.parent.right = n.right } } else if n.right == nil { // root node if n.parent == nil { this.root = n.left break } if n.parent.left == n { n.parent.left = n.left } else { n.parent.right = n.left } } else { // find the successor s := n.right for s.left != nil { s = s.left } np := n.parent nl := n.left nr := n.right sp := s.parent sr := s.right // Update parent s.parent = np if np == nil { this.root = s } else { if np.left == n { np.left = s } else { np.right = s } } // Update left s.left = nl s.left.parent = s // Update right if nr != s { s.right = nr s.right.parent = s } // Update successor parent if sp.left == s { sp.left = sr } else { sp.right = sr } } break } if n != nil { this.length-- } } func (this *SplayTree) String() string { if this.length == 0 { return "{}" } return this.root.String() } // Splay a node in the tree (send it to the top) func (this *SplayTree) splay(n *node) { // Already root, nothing to do if n.parent == nil { this.root = n return } p := n.parent g := p.parent // Zig if p == this.root { if n == p.left { p.rotateRight() } else { p.rotateLeft() } } else { // Zig-zig if n == p.left && p == g.left { g.rotateRight() p.rotateRight() } else if n == p.right && p == g.right { g.rotateLeft() p.rotateLeft() // Zig-zag } else if n == p.right && p == g.left { p.rotateLeft() g.rotateRight() } else if n == p.left && p == g.right { p.rotateRight() g.rotateLeft() } } this.splay(n) } // Swap two nodes in the tree func (this *SplayTree) swap(n1, n2 *node) { p1 := n1.parent l1 := n1.left r1 := n1.right p2 := n2.parent l2 := n2.left r2 := n2.right // Update node links n1.parent = p2 n1.left = l2 n1.right = r2 n2.parent = p1 n2.left = l1 n2.right = r1 // Update parent links if p1 != nil { if p1.left == n1 { p1.left = n2 } else { p1.right = n2 } } if p2 != nil { if p2.left == n2 { p2.left = n1 } else { p2.right = n1 } } if n1 == this.root { this.root = n2 } else if n2 == this.root { this.root = n1 } } // Node methods func (this *node) String() string { str := "{" + fmt.Sprint(this.value) + "|" if this.left != nil { str += this.left.String() } str += "|" if this.right != nil { str += this.right.String() } str += "}" return str } func (this *node) rotateLeft() { parent := this.parent pivot := this.right child := pivot.left if pivot == nil { return } // Update the parent if parent != nil { if parent.left == this { parent.left = pivot } else { parent.right = pivot } } // Update the pivot pivot.parent = parent pivot.left = this // Update the child if child != nil { child.parent = this } // Update this this.parent = pivot this.right = child } func (this *node) rotateRight() { parent := this.parent pivot := this.left child := pivot.right if pivot == nil { return } // Update the parent if parent != nil { if parent.left == this { parent.left = pivot } else { parent.right = pivot } } // Update the pivot pivot.parent = parent pivot.right = this if child != nil { child.parent = this } // Update this this.parent = pivot this.left = child }