Trees

A tree is a widely used data data structure that simulates a hierarchical tree structure, with a root value and subtrees of children, represented as a set of linked nodes; thus no cyclic links.

Implements Container interface.

  1. type Tree interface {
  2. containers.Container
  3. // Empty() bool
  4. // Size() int
  5. // Clear()
  6. // Values() []interface{}
  7. }

RedBlackTree

A red–black tree is a binary search tree with an extra bit of data per node, its color, which can be either red or black. The extra bit of storage ensures an approximately balanced tree by constraining how nodes are colored from any path from the root to the leaf. Thus, it is a data structure which is a type of self-balancing binary search tree.

The balancing of the tree is not perfect but it is good enough to allow it to guarantee searching in O(log n) time, where n is the total number of elements in the tree. The insertion and deletion operations, along with the tree rearrangement and recoloring, are also performed in O(log n) time. Wikipedia

Implements Tree, ReverseIteratorWithKey, JSONSerializer and JSONDeserializer interfaces.

Trees - 图1

  1. package main
  2. import (
  3. "fmt"
  4. rbt "github.com/emirpasic/gods/trees/redblacktree"
  5. )
  6. func main() {
  7. tree := rbt.NewWithIntComparator() // empty (keys are of type int)
  8. tree.Put(1, "x") // 1->x
  9. tree.Put(2, "b") // 1->x, 2->b (in order)
  10. tree.Put(1, "a") // 1->a, 2->b (in order, replacement)
  11. tree.Put(3, "c") // 1->a, 2->b, 3->c (in order)
  12. tree.Put(4, "d") // 1->a, 2->b, 3->c, 4->d (in order)
  13. tree.Put(5, "e") // 1->a, 2->b, 3->c, 4->d, 5->e (in order)
  14. tree.Put(6, "f") // 1->a, 2->b, 3->c, 4->d, 5->e, 6->f (in order)
  15. fmt.Println(tree)
  16. //
  17. // RedBlackTree
  18. // │ ┌── 6
  19. // │ ┌── 5
  20. // │ ┌── 4
  21. // │ │ └── 3
  22. // └── 2
  23. // └── 1
  24. _ = tree.Values() // []interface {}{"a", "b", "c", "d", "e", "f"} (in order)
  25. _ = tree.Keys() // []interface {}{1, 2, 3, 4, 5, 6} (in order)
  26. tree.Remove(2) // 1->a, 3->c, 4->d, 5->e, 6->f (in order)
  27. fmt.Println(tree)
  28. //
  29. // RedBlackTree
  30. // │ ┌── 6
  31. // │ ┌── 5
  32. // └── 4
  33. // │ ┌── 3
  34. // └── 1
  35. tree.Clear() // empty
  36. tree.Empty() // true
  37. tree.Size() // 0
  38. // Other:
  39. tree.Left() // gets the left-most (min) node
  40. tree.Right() // get the right-most (max) node
  41. tree.Floor(1) // get the floor node
  42. tree.Ceiling(1) // get the ceiling node
  43. }

Extending the red-black tree’s functionality has been demonstrated in the following example.

AVLTree

AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Lookup, insertion, and deletion all take O(log n) time in both the average and worst cases, where n is the number of nodes in the tree prior to the operation. Insertions and deletions may require the tree to be rebalanced by one or more tree rotations.

AVL trees are often compared with red–black trees because both support the same set of operations and take O(log n) time for the basic operations. For lookup-intensive applications, AVL trees are faster than red–black trees because they are more strictly balanced. Wikipedia

Implements Tree, ReverseIteratorWithKey, JSONSerializer and JSONDeserializer interfaces.

Trees - 图2
AVL tree with balance factors (green)

  1. package main
  2. import (
  3. "fmt"
  4. avl "github.com/emirpasic/gods/trees/avltree"
  5. )
  6. func main() {
  7. tree := avl.NewWithIntComparator() // empty(keys are of type int)
  8. tree.Put(1, "x") // 1->x
  9. tree.Put(2, "b") // 1->x, 2->b (in order)
  10. tree.Put(1, "a") // 1->a, 2->b (in order, replacement)
  11. tree.Put(3, "c") // 1->a, 2->b, 3->c (in order)
  12. tree.Put(4, "d") // 1->a, 2->b, 3->c, 4->d (in order)
  13. tree.Put(5, "e") // 1->a, 2->b, 3->c, 4->d, 5->e (in order)
  14. tree.Put(6, "f") // 1->a, 2->b, 3->c, 4->d, 5->e, 6->f (in order)
  15. fmt.Println(tree)
  16. //
  17. // AVLTree
  18. // │ ┌── 6
  19. // │ ┌── 5
  20. // └── 4
  21. // │ ┌── 3
  22. // └── 2
  23. // └── 1
  24. _ = tree.Values() // []interface {}{"a", "b", "c", "d", "e", "f"} (in order)
  25. _ = tree.Keys() // []interface {}{1, 2, 3, 4, 5, 6} (in order)
  26. tree.Remove(2) // 1->a, 3->c, 4->d, 5->e, 6->f (in order)
  27. fmt.Println(tree)
  28. //
  29. // AVLTree
  30. // │ ┌── 6
  31. // │ ┌── 5
  32. // └── 4
  33. // └── 3
  34. // └── 1
  35. tree.Clear() // empty
  36. tree.Empty() // true
  37. tree.Size() // 0
  38. }

BTree

B-tree is a self-balancing tree data structure that keeps data sorted and allows searches, sequential access, insertions, and deletions in logarithmic time. The B-tree is a generalization of a binary search tree in that a node can have more than two children.

According to Knuth’s definition, a B-tree of order m is a tree which satisfies the following properties:

  • Every node has at most m children.
  • Every non-leaf node (except root) has at least ⌈m/2⌉ children.
  • The root has at least two children if it is not a leaf node.
  • A non-leaf node with k children contains k−1 keys.
  • All leaves appear in the same level

Each internal node’s keys act as separation values which divide its subtrees. For example, if an internal node has 3 child nodes (or subtrees) then it must have 2 keys: a1 and a2. All values in the leftmost subtree will be less than a1, all values in the middle subtree will be between a1 and a2, and all values in the rightmost subtree will be greater than a2.Wikipedia

Implements Tree, ReverseIteratorWithKey, JSONSerializer and JSONDeserializer interfaces.

Trees - 图3

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/emirpasic/gods/trees/btree"
  5. )
  6. func main() {
  7. tree := btree.NewWithIntComparator(3) // empty (keys are of type int)
  8. tree.Put(1, "x") // 1->x
  9. tree.Put(2, "b") // 1->x, 2->b (in order)
  10. tree.Put(1, "a") // 1->a, 2->b (in order, replacement)
  11. tree.Put(3, "c") // 1->a, 2->b, 3->c (in order)
  12. tree.Put(4, "d") // 1->a, 2->b, 3->c, 4->d (in order)
  13. tree.Put(5, "e") // 1->a, 2->b, 3->c, 4->d, 5->e (in order)
  14. tree.Put(6, "f") // 1->a, 2->b, 3->c, 4->d, 5->e, 6->f (in order)
  15. tree.Put(7, "g") // 1->a, 2->b, 3->c, 4->d, 5->e, 6->f, 7->g (in order)
  16. fmt.Println(tree)
  17. // BTree
  18. // 1
  19. // 2
  20. // 3
  21. // 4
  22. // 5
  23. // 6
  24. // 7
  25. _ = tree.Values() // []interface {}{"a", "b", "c", "d", "e", "f", "g"} (in order)
  26. _ = tree.Keys() // []interface {}{1, 2, 3, 4, 5, 6, 7} (in order)
  27. tree.Remove(2) // 1->a, 3->c, 4->d, 5->e, 6->f (in order)
  28. fmt.Println(tree)
  29. // BTree
  30. // 1
  31. // 3
  32. // 4
  33. // 5
  34. // 6
  35. tree.Clear() // empty
  36. tree.Empty() // true
  37. tree.Size() // 0
  38. // Other:
  39. tree.Height() // gets the height of the tree
  40. tree.Left() // gets the left-most (min) node
  41. tree.LeftKey() // get the left-most (min) node's key
  42. tree.LeftValue() // get the left-most (min) node's value
  43. tree.Right() // get the right-most (max) node
  44. tree.RightKey() // get the right-most (max) node's key
  45. tree.RightValue() // get the right-most (max) node's value
  46. }

BinaryHeap

A binary heap is a tree created using a binary tree. It can be seen as a binary tree with two additional constraints:

  • Shape property:

    A binary heap is a complete binary tree; that is, all levels of the tree, except possibly the last one (deepest) are fully filled, and, if the last level of the tree is not complete, the nodes of that level are filled from left to right.

  • Heap property:

    All nodes are either greater than or equal to or less than or equal to each of its children, according to a comparison predicate defined for the heap. Wikipedia

Implements Tree, ReverseIteratorWithIndex, JSONSerializer and JSONDeserializer interfaces.

Trees - 图4

  1. package main
  2. import (
  3. "github.com/emirpasic/gods/trees/binaryheap"
  4. "github.com/emirpasic/gods/utils"
  5. )
  6. func main() {
  7. // Min-heap
  8. heap := binaryheap.NewWithIntComparator() // empty (min-heap)
  9. heap.Push(2) // 2
  10. heap.Push(3) // 2, 3
  11. heap.Push(1) // 1, 3, 2
  12. heap.Values() // 1, 3, 2
  13. _, _ = heap.Peek() // 1,true
  14. _, _ = heap.Pop() // 1, true
  15. _, _ = heap.Pop() // 2, true
  16. _, _ = heap.Pop() // 3, true
  17. _, _ = heap.Pop() // nil, false (nothing to pop)
  18. heap.Push(1) // 1
  19. heap.Clear() // empty
  20. heap.Empty() // true
  21. heap.Size() // 0
  22. // Max-heap
  23. inverseIntComparator := func(a, b interface{}) int {
  24. return -utils.IntComparator(a, b)
  25. }
  26. heap = binaryheap.NewWith(inverseIntComparator) // empty (min-heap)
  27. heap.Push(2, 3, 1) // 3, 2, 1 (bulk optimized)
  28. heap.Values() // 3, 2, 1
  29. }