BST by golang
This commit is contained in:
parent
8ba39161a9
commit
ccf862c519
145
go/24_tree/BinarySearchTree.go
Normal file
145
go/24_tree/BinarySearchTree.go
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package _4_tree
|
||||||
|
|
||||||
|
type BST struct {
|
||||||
|
*BinaryTree
|
||||||
|
//比对函数,0:v==nodeV,正数:v>nodeV,负数:v<nodeV
|
||||||
|
compareFunc func(v, nodeV interface{}) int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBST(rootV interface{}, compareFunc func(v, nodeV interface{}) int) *BST {
|
||||||
|
if nil == compareFunc {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &BST{BinaryTree: NewBinaryTree(rootV), compareFunc: compareFunc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *BST) Find(v interface{}) *Node {
|
||||||
|
p := this.root
|
||||||
|
for nil != p {
|
||||||
|
compareResult := this.compareFunc(v, p.data)
|
||||||
|
if compareResult == 0 {
|
||||||
|
return p
|
||||||
|
} else if compareResult > 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
|
||||||
|
}
|
145
go/24_tree/BinarySearchTree_test.go
Normal file
145
go/24_tree/BinarySearchTree_test.go
Normal file
@ -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()
|
||||||
|
}
|
65
go/24_tree/BinaryTree.go
Normal file
65
go/24_tree/BinaryTree.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
30
go/24_tree/BinaryTree_test.go
Normal file
30
go/24_tree/BinaryTree_test.go
Normal file
@ -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()
|
||||||
|
}
|
72
go/24_tree/StackBasedOnArray.go
Normal file
72
go/24_tree/StackBasedOnArray.go
Normal file
@ -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])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
go/24_tree/TreeNode.go
Normal file
17
go/24_tree/TreeNode.go
Normal file
@ -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)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user