forked from wangzheng0822/algo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request wangzheng0822#155 from scissorsfeet/master
BST by golang
- Loading branch information
Showing
6 changed files
with
474 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() | ||
} |
Oops, something went wrong.