From bd4c75a98e77a4e7f0a9b05258623a72bf81669b Mon Sep 17 00:00:00 2001 From: John Date: Fri, 10 May 2019 22:29:06 +0800 Subject: [PATCH] add AVLTree container for gtee --- g/container/gtree/gtree_avltree.go | 689 ++++++++++++++++++++++++ g/container/gtree/gtree_btree.go | 40 +- g/container/gtree/gtree_redblacktree.go | 3 +- geg/container/gtree/gtree_avltree.go | 21 + 4 files changed, 731 insertions(+), 22 deletions(-) create mode 100644 g/container/gtree/gtree_avltree.go create mode 100644 geg/container/gtree/gtree_avltree.go diff --git a/g/container/gtree/gtree_avltree.go b/g/container/gtree/gtree_avltree.go new file mode 100644 index 000000000..af1416213 --- /dev/null +++ b/g/container/gtree/gtree_avltree.go @@ -0,0 +1,689 @@ +// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtree + +import ( + "fmt" + "github.com/gogf/gf/g/container/gvar" + "github.com/gogf/gf/g/internal/rwmutex" +) + +// AVLTree holds elements of the AVL tree. +type AVLTree struct { + mu *rwmutex.RWMutex + root *AVLTreeNode + comparator func(v1, v2 interface{}) int + size int +} + +// AVLTreeNode is a single element within the tree. +type AVLTreeNode struct { + Key interface{} + Value interface{} + parent *AVLTreeNode + children [2]*AVLTreeNode + b int8 +} + +// NewAVLTree instantiates an AVL tree with the custom comparator. +// The param used to specify whether using tree in un-concurrent-safety, +// which is false in default. +func NewAVLTree(comparator func(v1, v2 interface{}) int, unsafe...bool) *AVLTree { + return &AVLTree{ + mu : rwmutex.New(unsafe...), + comparator: comparator, + } +} + +// Clone returns a new tree with a copy of current tree. +func (tree *AVLTree) Clone(unsafe ...bool) *AVLTree { + newTree := NewAVLTree(tree.comparator, !tree.mu.IsSafe()) + newTree.Sets(tree.Map()) + return newTree +} + +// Set inserts node into the tree. +func (tree *AVLTree) Set(key interface{}, value interface{}) { + tree.mu.Lock() + defer tree.mu.Unlock() + tree.put(key, value, nil, &tree.root) +} + +// Sets batch sets key-values to the tree. +func (tree *AVLTree) Sets(data map[interface{}]interface{}) { + tree.mu.Lock() + defer tree.mu.Unlock() + for key, value := range data { + tree.put(key, value, nil, &tree.root) + } +} + +// Search searches the tree with given . +// Second return parameter is true if key was found, otherwise false. +func (tree *AVLTree) Search(key interface{}) (value interface{}, found bool) { + tree.mu.RLock() + defer tree.mu.RUnlock() + return tree.doSearch(key) +} + +// doSearch searches the tree with given . +// Second return parameter is true if key was found, otherwise false. +func (tree *AVLTree) doSearch(key interface{}) (value interface{}, found bool) { + n := tree.root + for n != nil { + cmp := tree.comparator(key, n.Key) + switch { + case cmp == 0: return n.Value, true + case cmp < 0: n = n.children[0] + case cmp > 0: n = n.children[1] + } + } + return nil, false +} + +// Get searches the node in the tree by and returns its value or nil if key is not found in tree. +func (tree *AVLTree) Get(key interface{}) (value interface{}) { + value, _ = tree.Search(key) + return +} + +// doSetWithLockCheck checks whether value of the key exists with mutex.Lock, +// if not exists, set value to the map with given , +// or else just return the existing value. +// +// When setting value, if is type of , +// it will be executed with mutex.Lock of the hash map, +// and its return value will be set to the map with . +// +// It returns value with given . +func (tree *AVLTree) doSetWithLockCheck(key interface{}, value interface{}) interface{} { + tree.mu.Lock() + defer tree.mu.Unlock() + if v, ok := tree.doSearch(key); ok { + return v + } + if f, ok := value.(func() interface {}); ok { + value = f() + } + tree.put(key, value, nil, &tree.root) + return value +} + +// GetOrSet returns the value by key, +// or set value with given if not exist and returns this value. +func (tree *AVLTree) GetOrSet(key interface{}, value interface{}) interface{} { + if v, ok := tree.Search(key); !ok { + return tree.doSetWithLockCheck(key, value) + } else { + return v + } +} + +// GetOrSetFunc returns the value by key, +// or sets value with return value of callback function if not exist +// and returns this value. +func (tree *AVLTree) GetOrSetFunc(key interface{}, f func() interface{}) interface{} { + if v, ok := tree.Search(key); !ok { + return tree.doSetWithLockCheck(key, f()) + } else { + return v + } +} + +// GetOrSetFuncLock returns the value by key, +// or sets value with return value of callback function if not exist +// and returns this value. +// +// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function +// with mutex.Lock of the hash map. +func (tree *AVLTree) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} { + if v, ok := tree.Search(key); !ok { + return tree.doSetWithLockCheck(key, f) + } else { + return v + } +} + +// GetVar returns a gvar.Var with the value by given . +// The returned gvar.Var is un-concurrent safe. +func (tree *AVLTree) GetVar(key interface{}) *gvar.Var { + return gvar.New(tree.Get(key), true) +} + +// GetVarOrSet returns a gvar.Var with result from GetVarOrSet. +// The returned gvar.Var is un-concurrent safe. +func (tree *AVLTree) GetVarOrSet(key interface{}, value interface{}) *gvar.Var { + return gvar.New(tree.GetOrSet(key, value), true) +} + +// GetVarOrSetFunc returns a gvar.Var with result from GetOrSetFunc. +// The returned gvar.Var is un-concurrent safe. +func (tree *AVLTree) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var { + return gvar.New(tree.GetOrSetFunc(key, f), true) +} + +// GetVarOrSetFuncLock returns a gvar.Var with result from GetOrSetFuncLock. +// The returned gvar.Var is un-concurrent safe. +func (tree *AVLTree) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var { + return gvar.New(tree.GetOrSetFuncLock(key, f), true) +} + +// SetIfNotExist sets to the map if the does not exist, then return true. +// It returns false if exists, and would be ignored. +func (tree *AVLTree) SetIfNotExist(key interface{}, value interface{}) bool { + if !tree.Contains(key) { + tree.doSetWithLockCheck(key, value) + return true + } + return false +} + +// SetIfNotExistFunc sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +func (tree *AVLTree) SetIfNotExistFunc(key interface{}, f func() interface{}) bool { + if !tree.Contains(key) { + tree.doSetWithLockCheck(key, f()) + return true + } + return false +} + +// SetIfNotExistFuncLock sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +// +// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that +// it executes function with mutex.Lock of the hash map. +func (tree *AVLTree) SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool { + if !tree.Contains(key) { + tree.doSetWithLockCheck(key, f) + return true + } + return false +} + +// Contains checks whether exists in the tree. +func (tree *AVLTree) Contains(key interface{}) bool { + _, ok := tree.Search(key) + return ok +} + +// Remove remove the node from the tree by key. +// Key should adhere to the comparator's type assertion, otherwise method panics. +func (tree *AVLTree) Remove(key interface{}) { + tree.mu.Lock() + defer tree.mu.Unlock() + tree.remove(key, &tree.root) +} + +// Removes batch deletes values of the tree by . +func (tree *AVLTree) Removes(keys []interface{}) { + tree.mu.Lock() + defer tree.mu.Unlock() + for key := range keys { + tree.remove(key, &tree.root) + } +} + +// IsEmpty returns true if tree does not contain any nodes. +func (tree *AVLTree) IsEmpty() bool { + return tree.Size() == 0 +} + +// Size returns number of nodes in the tree. +func (tree *AVLTree) Size() int { + tree.mu.RLock() + defer tree.mu.RUnlock() + return tree.size +} + +// Keys returns all keys in asc order. +func (tree *AVLTree) Keys() []interface{} { + keys := make([]interface{}, tree.Size()) + index := 0 + tree.IteratorAsc(func(key, value interface{}) bool { + keys[index] = key + index++ + return true + }) + return keys +} + +// Values returns all values in asc order based on the key. +func (tree *AVLTree) Values() []interface{} { + values := make([]interface{}, tree.Size()) + index := 0 + tree.IteratorAsc(func(key, value interface{}) bool { + values[index] = key + index++ + return true + }) + return values +} + +// Left returns the minimum element of the AVL tree +// or nil if the tree is empty. +func (tree *AVLTree) Left() *AVLTreeNode { + tree.mu.RLock() + defer tree.mu.RUnlock() + node := tree.bottom(0) + if tree.mu.IsSafe() { + return &AVLTreeNode { + Key : node.Key, + Value : node.Value, + } + } + return node +} + +// Right returns the maximum element of the AVL tree +// or nil if the tree is empty. +func (tree *AVLTree) Right() *AVLTreeNode { + tree.mu.RLock() + defer tree.mu.RUnlock() + node := tree.bottom(1) + if tree.mu.IsSafe() { + return &AVLTreeNode { + Key : node.Key, + Value : node.Value, + } + } + return node +} + +// Floor Finds floor node of the input key, return the floor node or nil if no ceiling is found. +// Second return parameter is true if floor was found, otherwise false. +// +// Floor node is defined as the largest node that is smaller than or equal to the given node. +// A floor node may not be found, either because the tree is empty, or because +// all nodes in the tree is larger than the given node. +// +// Key should adhere to the comparator's type assertion, otherwise method panics. +func (tree *AVLTree) Floor(key interface{}) (floor *AVLTreeNode, found bool) { + tree.mu.RLock() + defer tree.mu.RUnlock() + found = false + n := tree.root + for n != nil { + c := tree.comparator(key, n.Key) + switch { + case c == 0: return n, true + case c < 0: n = n.children[0] + case c > 0: + floor, found = n, true + n = n.children[1] + } + } + if found { + return + } + return nil, false +} + +// Ceiling finds ceiling node of the input key, return the ceiling node or nil if no ceiling is found. +// Second return parameter is true if ceiling was found, otherwise false. +// +// Ceiling node is defined as the smallest node that is larger than or equal to the given node. +// A ceiling node may not be found, either because the tree is empty, or because +// all nodes in the tree is smaller than the given node. +// +// Key should adhere to the comparator's type assertion, otherwise method panics. +func (tree *AVLTree) Ceiling(key interface{}) (floor *AVLTreeNode, found bool) { + tree.mu.RLock() + defer tree.mu.RUnlock() + found = false + n := tree.root + for n != nil { + c := tree.comparator(key, n.Key) + switch { + case c == 0: return n, true + case c > 0: n = n.children[1] + case c < 0: + floor, found = n, true + n = n.children[0] + } + } + if found { + return + } + return nil, false +} + +// Clear removes all nodes from the tree. +func (tree *AVLTree) Clear() { + tree.mu.Lock() + defer tree.mu.Unlock() + tree.root = nil + tree.size = 0 +} + +// String returns a string representation of container +func (tree *AVLTree) String() string { + tree.mu.RLock() + defer tree.mu.RUnlock() + str := "AVLTree\n" + if tree.size != 0 { + output(tree.root, "", true, &str) + } + return str +} + +// Print prints the tree to stdout. +func (tree *AVLTree) Print() { + fmt.Println(tree.String()) +} + +func (node *AVLTreeNode) String() string { + return fmt.Sprintf("%v", node.Key) +} + +// Map returns all key-value items as map. +func (tree *AVLTree) Map() map[interface{}]interface{} { + m := make(map[interface{}]interface{}, tree.Size()) + tree.IteratorAsc(func(key, value interface{}) bool { + m[key] = value + return true + }) + return m +} + +// Flip exchanges key-value of the tree to value-key. +// Note that you should guarantee the value is the same type as key, +// or else the comparator would panic. +// +// If the type of value is different with key, you pass the new . +func (tree *AVLTree) Flip(comparator...func(v1, v2 interface{}) int) { + t := (*AVLTree)(nil) + if len(comparator) > 0 { + t = NewAVLTree(comparator[0], !tree.mu.IsSafe()) + } else { + t = NewAVLTree(tree.comparator, !tree.mu.IsSafe()) + } + tree.IteratorAsc(func(key, value interface{}) bool { + tree.put(value, key, nil, &tree.root) + return true + }) + tree.mu.Lock() + tree.root = t.root + tree.size = t.size + tree.mu.Unlock() +} + +// IteratorAsc iterates the tree in ascending order with given callback function . +// If returns true, then it continues iterating; or false to stop. +func (tree *AVLTree) IteratorAsc(f func (key, value interface{}) bool) { + tree.mu.RLock() + defer tree.mu.RUnlock() + node := tree.bottom(0) + for node != nil { + if !f(node.Key, node.Value) { + return + } + node = node.Next() + } +} + +// IteratorDesc iterates the tree in descending order with given callback function . +// If returns true, then it continues iterating; or false to stop. +func (tree *AVLTree) IteratorDesc(f func (key, value interface{}) bool) { + tree.mu.RLock() + defer tree.mu.RUnlock() + node := tree.bottom(1) + for node != nil { + if !f(node.Key, node.Value) { + return + } + node = node.Prev() + } +} + +func (tree *AVLTree) put(key interface{}, value interface{}, p *AVLTreeNode, qp **AVLTreeNode) bool { + q := *qp + if q == nil { + tree.size++ + *qp = &AVLTreeNode{Key: key, Value: value, parent: p} + return true + } + + c := tree.comparator(key, q.Key) + if c == 0 { + q.Key = key + q.Value = value + return false + } + + if c < 0 { + c = -1 + } else { + c = 1 + } + a := (c + 1) / 2 + var fix bool + fix = tree.put(key, value, q, &q.children[a]) + if fix { + return putFix(int8(c), qp) + } + return false +} + +func (tree *AVLTree) remove(key interface{}, qp **AVLTreeNode) bool { + q := *qp + if q == nil { + return false + } + + c := tree.comparator(key, q.Key) + if c == 0 { + tree.size-- + if q.children[1] == nil { + if q.children[0] != nil { + q.children[0].parent = q.parent + } + *qp = q.children[0] + return true + } + fix := removeMin(&q.children[1], &q.Key, &q.Value) + if fix { + return removeFix(-1, qp) + } + return false + } + + if c < 0 { + c = -1 + } else { + c = 1 + } + a := (c + 1) / 2 + fix := tree.remove(key, &q.children[a]) + if fix { + return removeFix(int8(-c), qp) + } + return false +} + +func removeMin(qp **AVLTreeNode, minKey *interface{}, minVal *interface{}) bool { + q := *qp + if q.children[0] == nil { + *minKey = q.Key + *minVal = q.Value + if q.children[1] != nil { + q.children[1].parent = q.parent + } + *qp = q.children[1] + return true + } + fix := removeMin(&q.children[0], minKey, minVal) + if fix { + return removeFix(1, qp) + } + return false +} + +func putFix(c int8, t **AVLTreeNode) bool { + s := *t + if s.b == 0 { + s.b = c + return true + } + + if s.b == -c { + s.b = 0 + return false + } + + if s.children[(c+1)/2].b == c { + s = singleRotate(c, s) + } else { + s = doubleRotate(c, s) + } + *t = s + return false +} + +func removeFix(c int8, t **AVLTreeNode) bool { + s := *t + if s.b == 0 { + s.b = c + return false + } + + if s.b == -c { + s.b = 0 + return true + } + + a := (c + 1) / 2 + if s.children[a].b == 0 { + s = rotate(c, s) + s.b = -c + *t = s + return false + } + + if s.children[a].b == c { + s = singleRotate(c, s) + } else { + s = doubleRotate(c, s) + } + *t = s + return true +} + +func singleRotate(c int8, s *AVLTreeNode) *AVLTreeNode { + s.b = 0 + s = rotate(c, s) + s.b = 0 + return s +} + +func doubleRotate(c int8, s *AVLTreeNode) *AVLTreeNode { + a := (c + 1) / 2 + r := s.children[a] + s.children[a] = rotate(-c, s.children[a]) + p := rotate(c, s) + + switch { + default: + s.b = 0 + r.b = 0 + case p.b == c: + s.b = -c + r.b = 0 + case p.b == -c: + s.b = 0 + r.b = c + } + + p.b = 0 + return p +} + +func rotate(c int8, s *AVLTreeNode) *AVLTreeNode { + a := (c + 1) / 2 + r := s.children[a] + s.children[a] = r.children[a^1] + if s.children[a] != nil { + s.children[a].parent = s + } + r.children[a^1] = s + r.parent = s.parent + s.parent = r + return r +} + +func (tree *AVLTree) bottom(d int) *AVLTreeNode { + n := tree.root + if n == nil { + return nil + } + + for c := n.children[d]; c != nil; c = n.children[d] { + n = c + } + return n +} + +// Prev returns the previous element in an inorder +// walk of the AVL tree. +func (node *AVLTreeNode) Prev() *AVLTreeNode { + return node.walk1(0) +} + +// Next returns the next element in an inorder +// walk of the AVL tree. +func (node *AVLTreeNode) Next() *AVLTreeNode { + return node.walk1(1) +} + +func (node *AVLTreeNode) walk1(a int) *AVLTreeNode { + if node == nil { + return nil + } + n := node + if n.children[a] != nil { + n = n.children[a] + for n.children[a^1] != nil { + n = n.children[a^1] + } + return n + } + + p := n.parent + for p != nil && p.children[a] == n { + n = p + p = p.parent + } + return p +} + +func output(node *AVLTreeNode, prefix string, isTail bool, str *string) { + if node.children[1] != nil { + newPrefix := prefix + if isTail { + newPrefix += "│ " + } else { + newPrefix += " " + } + output(node.children[1], newPrefix, false, str) + } + *str += prefix + if isTail { + *str += "└── " + } else { + *str += "┌── " + } + *str += node.String() + "\n" + if node.children[0] != nil { + newPrefix := prefix + if isTail { + newPrefix += " " + } else { + newPrefix += "│ " + } + output(node.children[0], newPrefix, true, str) + } +} \ No newline at end of file diff --git a/g/container/gtree/gtree_btree.go b/g/container/gtree/gtree_btree.go index fa0d30fa8..230a6a340 100644 --- a/g/container/gtree/gtree_btree.go +++ b/g/container/gtree/gtree_btree.go @@ -26,12 +26,12 @@ type BTree struct { // BTreeNode is a single element within the tree. type BTreeNode struct { Parent *BTreeNode - Entries []*BTreeNodeEntry // Contained keys in node - Children []*BTreeNode // Children nodes + Entries []*BTreeEntry // Contained keys in node + Children []*BTreeNode // Children nodes } -// BTreeNodeEntry represents the key-value pair contained within nodes. -type BTreeNodeEntry struct { +// BTreeEntry represents the key-value pair contained within nodes. +type BTreeEntry struct { Key interface{} Value interface{} } @@ -66,9 +66,9 @@ func (tree *BTree) Set(key interface{}, value interface{}) { // doSet inserts key-value pair node into the tree. // If key already exists, then its value is updated with the new value. func (tree *BTree) doSet(key interface{}, value interface{}) { - entry := &BTreeNodeEntry{Key: key, Value: value} + entry := &BTreeEntry{Key: key, Value: value} if tree.root == nil { - tree.root = &BTreeNode{Entries: []*BTreeNodeEntry{entry}, Children: []*BTreeNode{}} + tree.root = &BTreeNode{Entries: []*BTreeEntry{entry}, Children: []*BTreeNode{}} tree.size++ return } @@ -303,7 +303,7 @@ func (tree *BTree) Height() int { } // Left returns the left-most (min) entry or nil if tree is empty. -func (tree *BTree) Left() *BTreeNodeEntry { +func (tree *BTree) Left() *BTreeEntry { tree.mu.RLock() defer tree.mu.RUnlock() node := tree.left(tree.root) @@ -311,7 +311,7 @@ func (tree *BTree) Left() *BTreeNodeEntry { } // Right returns the right-most (max) entry or nil if tree is empty. -func (tree *BTree) Right() *BTreeNodeEntry { +func (tree *BTree) Right() *BTreeEntry { tree.mu.RLock() defer tree.mu.RUnlock() node := tree.right(tree.root) @@ -345,7 +345,7 @@ func (tree *BTree) Search(key interface{}) (value interface{}, found bool) { // Search searches the tree with given without mutex. // It returns the entry if found or otherwise nil. -func (tree *BTree) doSearch(key interface{}) *BTreeNodeEntry { +func (tree *BTree) doSearch(key interface{}) *BTreeEntry { node, index, found := tree.searchRecursively(tree.root, key) if found { return node.Entries[index] @@ -358,7 +358,7 @@ func (tree *BTree) Print() { fmt.Println(tree.String()) } -func (entry *BTreeNodeEntry) String() string { +func (entry *BTreeEntry) String() string { return fmt.Sprintf("%v", entry.Key) } @@ -551,14 +551,14 @@ func (tree *BTree) searchRecursively(startNode *BTreeNode, key interface{}) (nod } } -func (tree *BTree) insert(node *BTreeNode, entry *BTreeNodeEntry) (inserted bool) { +func (tree *BTree) insert(node *BTreeNode, entry *BTreeEntry) (inserted bool) { if tree.isLeaf(node) { return tree.insertIntoLeaf(node, entry) } return tree.insertIntoInternal(node, entry) } -func (tree *BTree) insertIntoLeaf(node *BTreeNode, entry *BTreeNodeEntry) (inserted bool) { +func (tree *BTree) insertIntoLeaf(node *BTreeNode, entry *BTreeEntry) (inserted bool) { insertPosition, found := tree.search(node, entry.Key) if found { node.Entries[insertPosition] = entry @@ -572,7 +572,7 @@ func (tree *BTree) insertIntoLeaf(node *BTreeNode, entry *BTreeNodeEntry) (inser return true } -func (tree *BTree) insertIntoInternal(node *BTreeNode, entry *BTreeNodeEntry) (inserted bool) { +func (tree *BTree) insertIntoInternal(node *BTreeNode, entry *BTreeEntry) (inserted bool) { insertPosition, found := tree.search(node, entry.Key) if found { node.Entries[insertPosition] = entry @@ -598,8 +598,8 @@ func (tree *BTree) splitNonRoot(node *BTreeNode) { middle := tree.middle() parent := node.Parent - left := &BTreeNode{Entries: append([]*BTreeNodeEntry(nil), node.Entries[:middle]...), Parent: parent} - right := &BTreeNode{Entries: append([]*BTreeNodeEntry(nil), node.Entries[middle+1:]...), Parent: parent} + left := &BTreeNode{Entries: append([]*BTreeEntry(nil), node.Entries[:middle]...), Parent: parent} + right := &BTreeNode{Entries: append([]*BTreeEntry(nil), node.Entries[middle+1:]...), Parent: parent} // Move children from the node to be split into left and right nodes if !tree.isLeaf(node) { @@ -629,8 +629,8 @@ func (tree *BTree) splitNonRoot(node *BTreeNode) { func (tree *BTree) splitRoot() { middle := tree.middle() - left := &BTreeNode{Entries: append([]*BTreeNodeEntry(nil), tree.root.Entries[:middle]...)} - right := &BTreeNode{Entries: append([]*BTreeNodeEntry(nil), tree.root.Entries[middle+1:]...)} + left := &BTreeNode{Entries: append([]*BTreeEntry(nil), tree.root.Entries[:middle]...)} + right := &BTreeNode{Entries: append([]*BTreeEntry(nil), tree.root.Entries[middle+1:]...)} // Move children from the node to be split into left and right nodes if !tree.isLeaf(tree.root) { @@ -642,7 +642,7 @@ func (tree *BTree) splitRoot() { // Root is a node with one entry and two children (left and right) newRoot := &BTreeNode{ - Entries: []*BTreeNodeEntry{tree.root.Entries[middle]}, + Entries: []*BTreeEntry{tree.root.Entries[middle]}, Children: []*BTreeNode{left, right}, } @@ -744,7 +744,7 @@ func (tree *BTree) rebalance(node *BTreeNode, deletedKey interface{}) { leftSibling, leftSiblingIndex := tree.leftSibling(node, deletedKey) if leftSibling != nil && len(leftSibling.Entries) > tree.minEntries() { // rotate right - node.Entries = append([]*BTreeNodeEntry{node.Parent.Entries[leftSiblingIndex]}, node.Entries...) // prepend parent's separator entry to node's entries + node.Entries = append([]*BTreeEntry{node.Parent.Entries[leftSiblingIndex]}, node.Entries...) // prepend parent's separator entry to node's entries node.Parent.Entries[leftSiblingIndex] = leftSibling.Entries[len(leftSibling.Entries)-1] tree.deleteEntry(leftSibling, len(leftSibling.Entries)-1) if !tree.isLeaf(leftSibling) { @@ -783,7 +783,7 @@ func (tree *BTree) rebalance(node *BTreeNode, deletedKey interface{}) { tree.deleteChild(node.Parent, rightSiblingIndex) } else if leftSibling != nil { // merge with left sibling - entries := append([]*BTreeNodeEntry(nil), leftSibling.Entries...) + entries := append([]*BTreeEntry(nil), leftSibling.Entries...) entries = append(entries, node.Parent.Entries[leftSiblingIndex]) node.Entries = append(entries, node.Entries...) deletedKey = node.Parent.Entries[leftSiblingIndex].Key diff --git a/g/container/gtree/gtree_redblacktree.go b/g/container/gtree/gtree_redblacktree.go index 8512c0e86..4b88a4019 100644 --- a/g/container/gtree/gtree_redblacktree.go +++ b/g/container/gtree/gtree_redblacktree.go @@ -53,7 +53,6 @@ func (tree *RedBlackTree) Clone(unsafe ...bool) *RedBlackTree { return newTree } - // Set inserts key-value item into the tree. func (tree *RedBlackTree) Set(key interface{}, value interface{}) { tree.mu.Lock() @@ -597,7 +596,7 @@ func (tree *RedBlackTree) output(node *RedBlackTreeNode, prefix string, isTail b } } -// Search searches the tree with given without mutex. +// doSearch searches the tree with given without mutex. // It returns the node if found or otherwise nil. func (tree *RedBlackTree) doSearch(key interface{}) *RedBlackTreeNode { node := tree.root diff --git a/geg/container/gtree/gtree_avltree.go b/geg/container/gtree/gtree_avltree.go new file mode 100644 index 000000000..f26d5c674 --- /dev/null +++ b/geg/container/gtree/gtree_avltree.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + "github.com/gogf/gf/g/container/gtree" +) + +func main() { + tree := gtree.NewAVLTree(func(v1, v2 interface{}) int { + return v1.(int) - v2.(int) + }) + for i := 0; i < 20; i++ { + tree.Set(i, i*10) + } + fmt.Println(tree.String()) + + tree.IteratorDesc(func(key, value interface{}) bool { + fmt.Println(key, value) + return true + }) +} \ No newline at end of file