BST by golang

This commit is contained in:
leotyliu(刘天一) 2018-11-15 16:07:29 +08:00
parent 8ba39161a9
commit ccf862c519
6 changed files with 474 additions and 0 deletions

View 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
}

View 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
View 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)
}
}

View 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()
}

View 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
View 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)
}