Skip to content

Commit

Permalink
fix: Tree package bug (TheAlgorithms#589)
Browse files Browse the repository at this point in the history
* add Parent to binary search tree

* refactor NIL in all trees

* add Successor and Predecessor to

* fix: tree package bug

* remove dummy variable leaf

* Refactoring: remove  method; make NIL a sentinel value for 3 trees, and eliminate nil in those implementations.

* change the method isRBTree to isRB

* fix:remove base struct, separate Node to three different nodes that complete Node Interface; still save NIL, but make it unexported

* Add more comments; Move Tree interface to tree_test package for future development.

* code tidy

* fix typo in comments
  • Loading branch information
guuzaa authored Jan 15, 2023
1 parent 83cff67 commit e5658c3
Show file tree
Hide file tree
Showing 9 changed files with 1,252 additions and 744 deletions.
309 changes: 239 additions & 70 deletions structure/tree/avl.go

Large diffs are not rendered by default.

164 changes: 105 additions & 59 deletions structure/tree/avl_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package tree_test

import (
"testing"

bt "github.com/TheAlgorithms/Go/structure/tree"
"math/rand"
"sort"
"testing"
"time"
)

func TestAVLPush(t *testing.T) {
Expand All @@ -12,51 +14,51 @@ func TestAVLPush(t *testing.T) {
tree.Push(5, 4, 3)

root := tree.Root
if root.Key != 4 {
t.Errorf("Root should have value = 4, not %v", root.Key)
if root.Key() != 4 {
t.Errorf("Root should have value = 4, not %v", root.Key())
}
if root.Height != 2 {
t.Errorf("Height of Root should be = 2, not %d", root.Height)
if root.Height() != 2 {
t.Errorf("Height of Root should be = 2, not %d", root.Height())
}

if root.Left.Key != 3 {
if root.Left().Key() != 3 {
t.Errorf("Left child should have value = 3")
}
if root.Left.Height != 1 {
if root.Left().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Left child should be 1")
}

if root.Right.Key != 5 {
if root.Right().Key() != 5 {
t.Errorf("Right child should have value = 5")
}
if root.Right.Height != 1 {
if root.Right().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Right should be 1")
}

})

t.Run("LRRotation-Test", func(t *testing.T) {
tree := bt.NewAVL[int]()
tree.Push(5, 3, 4)

root := tree.Root
if root.Key != 4 {
t.Errorf("Root should have value = 4")
if root.Key() != 4 {
t.Errorf("Root should have value = 4, not %v", root.Key())
}
if root.Height != 2 {
t.Errorf("Height of Root should be = 2")
if root.Height() != 2 {
t.Errorf("Height of Root should be = 2, not %d", root.Height())
}

if root.Left.Key != 3 {
if root.Left().Key() != 3 {
t.Errorf("Left child should have value = 3")
}
if root.Left.Height != 1 {
if root.Left().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Left child should be 1")
}

if root.Right.Key != 5 {
if root.Right().Key() != 5 {
t.Errorf("Right child should have value = 5")
}
if root.Right.Height != 1 {
if root.Right().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Right should be 1")
}
})
Expand All @@ -68,52 +70,52 @@ func TestAVLPush(t *testing.T) {
tree.Push(5)

root := tree.Root
if root.Key != 4 {
t.Errorf("Root should have value = 4")
if root.Key() != 4 {
t.Errorf("Root should have value = 4, not %v", root.Key())
}
if root.Height != 2 {
t.Errorf("Height of Root should be = 2")
if root.Height() != 2 {
t.Errorf("Height of Root should be = 2, not %d", root.Height())
}

if root.Left.Key != 3 {
if root.Left().Key() != 3 {
t.Errorf("Left child should have value = 3")
}
if root.Left.Height != 1 {
if root.Left().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Left child should be 1")
}

if root.Right.Key != 5 {
if root.Right().Key() != 5 {
t.Errorf("Right child should have value = 5")
}
if root.Right.Height != 1 {
if root.Right().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Right should be 1")
}
})
t.Run("RLRotaion-Test", func(t *testing.T) {
t.Run("RLRotation-Test", func(t *testing.T) {
tree := bt.NewAVL[int]()
tree.Push(3)
tree.Push(5)
tree.Push(4)

root := tree.Root
if root.Key != 4 {
if root.Key() != 4 {
t.Errorf("Root should have value = 4")
}
if root.Height != 2 {
if root.Height() != 2 {
t.Errorf("Height of Root should be = 2")
}

if root.Left.Key != 3 {
if root.Left().Key() != 3 {
t.Errorf("Left child should have value = 3")
}
if root.Left.Height != 1 {
if root.Left().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Left child should be 1")
}

if root.Right.Key != 5 {
if root.Right().Key() != 5 {
t.Errorf("Right child should have value = 5")
}
if root.Right.Height != 1 {
if root.Right().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Right should be 1")
}
})
Expand All @@ -122,6 +124,9 @@ func TestAVLPush(t *testing.T) {
func TestAVLDelete(t *testing.T) {
t.Run("LLRotation-Test", func(t *testing.T) {
tree := bt.NewAVL[int]()
if tree.Delete(5) {
t.Errorf("There is no node, whose value is 5")
}

tree.Push(5)
tree.Push(4)
Expand All @@ -137,24 +142,24 @@ func TestAVLDelete(t *testing.T) {
}

root := tree.Root
if root.Key != 3 {
if root.Key() != 3 {
t.Errorf("Root should have value = 3")
}
if root.Height != 2 {
if root.Height() != 2 {
t.Errorf("Height of Root should be = 2")
}

if root.Left.Key != 2 {
if root.Left().Key() != 2 {
t.Errorf("Left child should have value = 2")
}
if root.Left.Height != 1 {
if root.Left().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Left child should be 1")
}

if root.Right.Key != 4 {
if root.Right().Key() != 4 {
t.Errorf("Right child should have value = 5")
}
if root.Right.Height != 1 {
if root.Right().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Right should be 1")
}
})
Expand All @@ -164,6 +169,7 @@ func TestAVLDelete(t *testing.T) {

tree.Push(10)
tree.Push(8)
tree.Push(8)
tree.Push(6)
tree.Push(7)

Expand All @@ -176,24 +182,24 @@ func TestAVLDelete(t *testing.T) {
}

root := tree.Root
if root.Key != 7 {
if root.Key() != 7 {
t.Errorf("Root should have value = 7")
}
if root.Height != 2 {
if root.Height() != 2 {
t.Errorf("Height of Root should be = 2")
}

if root.Left.Key != 6 {
if root.Left().Key() != 6 {
t.Errorf("Left child should have value = 6")
}
if root.Left.Height != 1 {
if root.Left().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Left child should be 1")
}

if root.Right.Key != 8 {
if root.Right().Key() != 8 {
t.Errorf("Right child should have value = 8")
}
if root.Right.Height != 1 {
if root.Right().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Right should be 1")
}

Expand All @@ -204,6 +210,7 @@ func TestAVLDelete(t *testing.T) {

tree.Push(2)
tree.Push(3)
tree.Push(3)
tree.Push(4)
tree.Push(5)

Expand All @@ -216,60 +223,99 @@ func TestAVLDelete(t *testing.T) {
}

root := tree.Root
if root.Key != 4 {
if root.Key() != 4 {
t.Errorf("Root should have value = 4")
}
if root.Height != 2 {
if root.Height() != 2 {
t.Errorf("Height of Root should be = 2")
}

if root.Left.Key != 3 {
if root.Left().Key() != 3 {
t.Errorf("Left child should have value = 3")
}
if root.Left.Height != 1 {
if root.Left().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Left child should be 1")
}

if root.Right.Key != 5 {
if root.Right().Key() != 5 {
t.Errorf("Right child should have value = 5")
}
if root.Right.Height != 1 {
if root.Right().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Right should be 1")
}

})

t.Run("RLRotaion-Test", func(t *testing.T) {
t.Run("RLRotation-Test", func(t *testing.T) {
tree := bt.NewAVL[int]()

tree.Push(7)
tree.Push(6)
tree.Push(6)
tree.Push(9)
tree.Push(8)

tree.Delete(6)

root := tree.Root
if root.Key != 8 {
if root.Key() != 8 {
t.Errorf("Root should have value = 8")
}
if root.Height != 2 {
if root.Height() != 2 {
t.Errorf("Height of Root should be = 2")
}

if root.Left.Key != 7 {
if root.Left().Key() != 7 {
t.Errorf("Left child should have value = 7")
}
if root.Left.Height != 1 {
if root.Left().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Left child should be 1")
}

if root.Right.Key != 9 {
if root.Right().Key() != 9 {
t.Errorf("Right child should have value = 9")
}
if root.Right.Height != 1 {
if root.Right().(*bt.AVLNode[int]).Height() != 1 {
t.Errorf("Height of Right should be 1")
}

})

t.Run("Random Test", func(t *testing.T) {
nums := []int{100, 500, 1000, 10_000}
for _, n := range nums {
rand.Seed(time.Now().Unix())
tree := bt.NewAVL[int]()
nums := rand.Perm(n)
tree.Push(nums...)

rets := tree.InOrder()
if !sort.IntsAreSorted(rets) {
t.Error("Error with Push")
}

if res, ok := tree.Min(); !ok || res != rets[0] {
t.Errorf("Error with Min, get %d, want: %d", res, rets[0])
}

if res, ok := tree.Max(); !ok || res != rets[n-1] {
t.Errorf("Error with Max, get %d, want: %d", res, rets[n-1])
}

for i := 0; i < n-1; i++ {
if ret, ok := tree.Successor(rets[0]); ret != rets[1] || !ok {
t.Error("Error with Successor")
}
if ret, ok := tree.Predecessor(rets[1]); ret != rets[0] || !ok {
t.Error("Error with Predecessor")
}

ok := tree.Delete(nums[i])
rets = tree.InOrder()
if !ok || !sort.IntsAreSorted(rets) {
t.Errorf("Error With Delete")
}
}
}
})
}
Loading

0 comments on commit e5658c3

Please sign in to comment.