commit
1ac0b0af14
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