1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00

feat: add BSTree which is binary search tree

This commit is contained in:
dudaodong
2022-02-21 16:48:27 +08:00
parent e7ee2ed7cf
commit b2b6710a1b
4 changed files with 191 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
package datastructure
import (
"math"
"github.com/duke-git/lancet/datastructure"
"github.com/duke-git/lancet/lancetconstraints"
)
// BSTree is a binary search tree data structure in which each node has at most two children,
// which are referred to as the left child and the right child.
// In BSTree: leftNode < rootNode < rightNode
// type T should implments Compare function of lancetconstraints.Comparator interface
type BSTree[T any] struct {
root *datastructure.TreeNode[T]
}
// NewBSTree create a BSTree pointer
func NewBSTree[T any](rootData T) *BSTree[T] {
root := datastructure.NewTreeNode(rootData)
return &BSTree[T]{root}
}
// Insert data into BSTree
func (t *BSTree[T]) Insert(data T, comparator lancetconstraints.Comparator) {
root := t.root
newNode := datastructure.NewTreeNode(data)
if root == nil {
t.root = newNode
} else {
insertTreeNode(root, newNode, comparator)
}
}
// NodeLevel get node level in BSTree
func (t *BSTree[T]) NodeLevel(node *datastructure.TreeNode[T]) int {
if node == nil {
return 0
}
left := float64(t.NodeLevel(node.Left))
right := float64(t.NodeLevel(node.Right))
return int(math.Max(left, right)) + 1
}
// Print the bstree structure
func (t *BSTree[T]) Print() {
maxLevel := t.NodeLevel(t.root)
nodes := []*datastructure.TreeNode[T]{t.root}
printTreeNodes(nodes, 1, maxLevel)
}

View File

@@ -0,0 +1,29 @@
package datastructure
import "testing"
type intComparator struct{}
func (c *intComparator) Compare(v1, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
func TestBSTree_Insert(t *testing.T) {
bstree := NewBSTree(6)
comparator := &intComparator{}
bstree.Insert(7, comparator)
bstree.Insert(5, comparator)
bstree.Insert(2, comparator)
bstree.Insert(4, comparator)
bstree.Print()
}

View File

@@ -0,0 +1,99 @@
package datastructure
import (
"fmt"
"math"
"github.com/duke-git/lancet/datastructure"
"github.com/duke-git/lancet/lancetconstraints"
)
func insertTreeNode[T any](rootNode, newNode *datastructure.TreeNode[T], comparator lancetconstraints.Comparator) {
if comparator.Compare(newNode.Data, rootNode.Data) == -1 {
if rootNode.Left == nil {
rootNode.Left = newNode
} else {
insertTreeNode(rootNode.Left, newNode, comparator)
}
} else {
if rootNode.Right == nil {
rootNode.Right = newNode
} else {
insertTreeNode(rootNode.Right, newNode, comparator)
}
}
}
func printTreeNodes[T any](nodes []*datastructure.TreeNode[T], level, maxLevel int) {
if len(nodes) == 0 || isAllNil(nodes) {
return
}
floor := maxLevel - level
endgeLines := int(math.Pow(float64(2), (math.Max(float64(floor)-1, 0))))
firstSpaces := int(math.Pow(float64(2), float64(floor))) - 1
betweenSpaces := int(math.Pow(float64(2), float64(floor)+1)) - 1
printSpaces(firstSpaces)
newNodes := []*datastructure.TreeNode[T]{}
for _, node := range nodes {
if node != nil {
fmt.Printf("%v", node.Data)
newNodes = append(newNodes, node.Left)
newNodes = append(newNodes, node.Right)
} else {
newNodes = append(newNodes, nil)
newNodes = append(newNodes, nil)
printSpaces(1)
}
printSpaces(betweenSpaces)
}
fmt.Println("")
for i := 1; i <= endgeLines; i++ {
for j := 0; j < len(nodes); j++ {
printSpaces(firstSpaces - i)
if nodes[j] == nil {
printSpaces(endgeLines + endgeLines + i + 1)
continue
}
if nodes[j].Left != nil {
fmt.Print("/")
} else {
printSpaces(1)
}
printSpaces(i + i - 1)
if nodes[j].Right != nil {
fmt.Print("\\")
} else {
printSpaces(1)
}
printSpaces(endgeLines + endgeLines - 1)
}
fmt.Println("")
}
printTreeNodes(newNodes, level+1, maxLevel)
}
// printSpaces
func printSpaces(n int) {
for i := 0; i < n; i++ {
fmt.Print(" ")
}
}
func isAllNil[T any](nodes []*datastructure.TreeNode[T]) bool {
for _, v := range nodes {
if v != nil {
return false
}
}
return true
}