diff --git a/go/24_tree/BinarySearchTree.go b/go/24_tree/BinarySearchTree.go new file mode 100644 index 0000000..0e39e35 --- /dev/null +++ b/go/24_tree/BinarySearchTree.go @@ -0,0 +1,145 @@ +package _4_tree + +type BST struct { + *BinaryTree + //比对函数,0:v==nodeV,正数:v>nodeV,负数:v 0 { //v > nodeV + p = p.right + } else { //v < nodeV + p = p.left + } + } + return nil +} + +func (this *BST) Insert(v interface{}) bool { + p := this.root + for nil != p { + compareResult := this.compareFunc(v, p.data) + if compareResult == 0 { + return false + } else if compareResult > 0 { + if nil == p.right { + p.right = NewNode(v) + break + } + p = p.right + } else { + if nil == p.left { + p.left = NewNode(v) + break + } + p = p.left + } + } + return true +} + +func (this *BST) Delete(v interface{}) bool { + var pp *Node = nil + p := this.root + deleteLeft := false + for nil != p { + compareResult := this.compareFunc(v, p.data) + if compareResult > 0 { + pp = p + p = p.right + deleteLeft = false + } else if compareResult < 0 { + pp = p + p = p.left + deleteLeft = true + } else { + break + } + } + + if nil == p { //需要删除的节点不存在 + return false + } else if nil == p.left && nil == p.right { //删除的是一个叶子节点 + if nil != pp { + if deleteLeft { + pp.left = nil + } else { + pp.right = nil + } + } else { //根节点 + this.root = nil + } + } else if nil != p.right { //删除的是一个有右孩子,不一定有左孩子的节点 + //找到p节点右孩子的最小节点 + pq := p + q := p.right //向右走一步 + fromRight := true + for nil != q.left { //向左走到底 + pq = q + q = q.left + fromRight = false + } + if fromRight { + pq.right = nil + } else { + pq.left = nil + } + q.left = p.left + q.right = p.right + if nil == pp { //根节点被删除 + this.root = q + } else { + if deleteLeft { + pq.left = q + } else { + pq.right = q + } + } + } else { //删除的是一个只有左孩子的节点 + if nil != pp { + if deleteLeft { + pp.left = p.left + } else { + pp.right = p.left + } + } else { + if deleteLeft { + this.root = p.left + } else { + this.root = p.left + } + } + } + + return true + +} + +func (this *BST) Min() *Node { + p := this.root + for nil != p.left { + p = p.left + } + return p +} + +func (this *BST) Max() *Node { + p := this.root + for nil != p.right { + p = p.right + } + return p +} diff --git a/go/24_tree/BinarySearchTree_test.go b/go/24_tree/BinarySearchTree_test.go new file mode 100644 index 0000000..f9dbb61 --- /dev/null +++ b/go/24_tree/BinarySearchTree_test.go @@ -0,0 +1,145 @@ +package _4_tree + +import "testing" + +var compareFunc = func(v, nodeV interface{}) int { + vInt := v.(int) + nodeVInt := nodeV.(int) + + if vInt > nodeVInt { + return 1 + } else if vInt < nodeVInt { + return -1 + } + return 0 +} + +func TestBST_Find(t *testing.T) { + bst := NewBST(1, compareFunc) + + bst.Insert(3) + bst.Insert(1) + bst.Insert(2) + bst.Insert(7) + bst.Insert(5) + + t.Log(bst.Find(2)) +} + +func TestBST_Insert(t *testing.T) { + bst := NewBST(1, compareFunc) + + bst.Insert(3) + bst.Insert(1) + bst.Insert(2) + bst.Insert(7) + bst.Insert(5) + + bst.InOrderTraverse() +} + +func TestBST_Min(t *testing.T) { + bst := NewBST(1, compareFunc) + + bst.Insert(3) + bst.Insert(1) + bst.Insert(2) + bst.Insert(7) + bst.Insert(5) + + t.Log(bst.Min()) +} + +func TestBST_Max(t *testing.T) { + bst := NewBST(1, compareFunc) + + bst.Insert(3) + bst.Insert(1) + bst.Insert(2) + bst.Insert(7) + bst.Insert(5) + + t.Log(bst.Max()) +} + +func TestBST_DeleteA(t *testing.T) { + bst := NewBST(1, compareFunc) + + bst.Insert(3) + bst.Insert(2) + bst.Insert(7) + bst.Insert(5) + + t.Log(bst.Delete(7)) + + bst.InOrderTraverse() +} + +func TestBST_DeleteB(t *testing.T) { + bst := NewBST(1, compareFunc) + + t.Log(bst.Delete(1)) + t.Log(bst.root) + + bst.InOrderTraverse() +} + +func TestBST_DeleteC(t *testing.T) { + bst := NewBST(1, compareFunc) + + bst.Insert(3) + bst.Insert(2) + bst.Insert(7) + bst.Insert(5) + + t.Log(bst.Delete(1)) + + bst.InOrderTraverse() +} + +func TestBST_DeleteD(t *testing.T) { + bst := NewBST(1, compareFunc) + + bst.Insert(3) + bst.Insert(2) + bst.Insert(5) + + t.Log(bst.Delete(1)) + + bst.InOrderTraverse() +} +func TestBST_DeleteE(t *testing.T) { + bst := NewBST(5, compareFunc) + + bst.Insert(3) + bst.Insert(2) + bst.Insert(4) + bst.Insert(1) + + t.Log(bst.Delete(5)) + bst.InOrderTraverse() +} + +func TestBST_DeleteF(t *testing.T) { + bst := NewBST(5, compareFunc) + + bst.Insert(3) + bst.Insert(2) + bst.Insert(4) + bst.Insert(1) + + t.Log(bst.Delete(2)) + bst.InOrderTraverse() +} + +func TestBST_DeleteG(t *testing.T) { + bst := NewBST(5, compareFunc) + + bst.Insert(3) + bst.Insert(2) + bst.Insert(4) + bst.Insert(1) + + t.Log(bst.Delete(1)) + bst.InOrderTraverse() +} diff --git a/go/24_tree/BinaryTree.go b/go/24_tree/BinaryTree.go new file mode 100644 index 0000000..db9f8ae --- /dev/null +++ b/go/24_tree/BinaryTree.go @@ -0,0 +1,65 @@ +package _4_tree + +import "fmt" + +type BinaryTree struct { + root *Node +} + +func NewBinaryTree(rootV interface{}) *BinaryTree { + return &BinaryTree{NewNode(rootV)} +} + +func (this *BinaryTree) InOrderTraverse() { + p := this.root + s := NewArrayStack() + + for !s.IsEmpty() || nil != p { + if nil != p { + s.Push(p) + p = p.left + } else { + tmp := s.Pop().(*Node) + fmt.Printf("%+v ", tmp.data) + p = tmp.right + } + } + fmt.Println() +} + +func (this *BinaryTree) PreOrderTraverse() { + p := this.root + s := NewArrayStack() + + for !s.IsEmpty() || nil != p { + if nil != p { + fmt.Printf("%+v ", p.data) + s.Push(p) + p = p.left + } else { + p = s.Pop().(*Node).right + } + } + + fmt.Println() +} + +func (this *BinaryTree) PostOrderTraverse() { + s1 := NewArrayStack() + s2 := NewArrayStack() + s1.Push(this.root) + for !s1.IsEmpty() { + p := s1.Pop().(*Node) + s2.Push(p) + if nil != p.left { + s1.Push(p.left) + } + if nil != p.right { + s1.Push(p.right) + } + } + + for !s2.IsEmpty() { + fmt.Printf("%+v ", s2.Pop().(*Node).data) + } +} diff --git a/go/24_tree/BinaryTree_test.go b/go/24_tree/BinaryTree_test.go new file mode 100644 index 0000000..484c3b2 --- /dev/null +++ b/go/24_tree/BinaryTree_test.go @@ -0,0 +1,30 @@ +package _4_tree + +import "testing" + +func TestBinaryTree_InOrderTraverse(t *testing.T) { + binaryTree := NewBinaryTree(1) + binaryTree.root.left = NewNode(3) + binaryTree.root.right = NewNode(4) + binaryTree.root.right.left = NewNode(5) + + binaryTree.InOrderTraverse() +} + +func TestBinaryTree_PreOrderTraverse(t *testing.T) { + binaryTree := NewBinaryTree(1) + binaryTree.root.left = NewNode(3) + binaryTree.root.right = NewNode(4) + binaryTree.root.right.left = NewNode(5) + + binaryTree.PreOrderTraverse() +} + +func TestBinaryTree_PostOrderTraverse(t *testing.T) { + binaryTree := NewBinaryTree(1) + binaryTree.root.left = NewNode(3) + binaryTree.root.right = NewNode(4) + binaryTree.root.right.left = NewNode(5) + + binaryTree.PostOrderTraverse() +} diff --git a/go/24_tree/StackBasedOnArray.go b/go/24_tree/StackBasedOnArray.go new file mode 100644 index 0000000..e1c585f --- /dev/null +++ b/go/24_tree/StackBasedOnArray.go @@ -0,0 +1,72 @@ +package _4_tree + +import "fmt" + +/* +基于数组实现的栈 +*/ + +type ArrayStack struct { + //数据 + data []interface{} + //栈顶指针 + top int +} + +func NewArrayStack() *ArrayStack { + return &ArrayStack{ + data: make([]interface{}, 0, 32), + top: -1, + } +} + +func (this *ArrayStack) IsEmpty() bool { + if this.top < 0 { + return true + } + return false +} + +func (this *ArrayStack) Push(v interface{}) { + if this.top < 0 { + this.top = 0 + } else { + this.top += 1 + } + + if this.top > len(this.data)-1 { + this.data = append(this.data, v) + } else { + this.data[this.top] = v + } +} + +func (this *ArrayStack) Pop() interface{} { + if this.IsEmpty() { + return nil + } + v := this.data[this.top] + this.top -= 1 + return v +} + +func (this *ArrayStack) Top() interface{} { + if this.IsEmpty() { + return nil + } + return this.data[this.top] +} + +func (this *ArrayStack) Flush() { + this.top = -1 +} + +func (this *ArrayStack) Print() { + if this.IsEmpty() { + fmt.Println("empty statck") + } else { + for i := this.top; i >= 0; i-- { + fmt.Println(this.data[i]) + } + } +} diff --git a/go/24_tree/TreeNode.go b/go/24_tree/TreeNode.go new file mode 100644 index 0000000..775cf46 --- /dev/null +++ b/go/24_tree/TreeNode.go @@ -0,0 +1,17 @@ +package _4_tree + +import "fmt" + +type Node struct { + data interface{} + left *Node + right *Node +} + +func NewNode(data interface{}) *Node { + return &Node{data: data} +} + +func (this *Node) String() string { + return fmt.Sprintf("v:%+v, left:%+v, right:%+v", this.data, this.left, this.right) +}