Go实现二叉查找树
2018-02-24 15:35
225 查看
-----------------------------------------binarysearchtree.go----------------------------------------
package binarysearchtree
import (
"fmt"
"container/list"
"errors"
)
var (
ErrComparatorIsNil = errors.New("comparator of BinarySearchTree is nil")
ErrTreeIsEmpty = errors.New("BinarySearchTree is empty")
)
type (
Comparator interface {
Compare(x interface{}, y *BinaryNode) int
}
BinaryNode struct {
Val interface{}
Left, Right *BinaryNode
}
BinarySearchTree struct {
Root *BinaryNode
Comparator Comparator
}
)
// 创建二叉搜索树时必须提供排序规则
func New(comparator Comparator) *BinarySearchTree {
if comparator == nil {
panic(ErrComparatorIsNil)
}
return &BinarySearchTree{nil, comparator}
}
// 清空数据
func (tree *BinarySearchTree) MakeEmpty() {
tree.Root = nil
}
func (tree *BinarySearchTree) IsEmpty() bool {
return tree.Root == nil
}
func (tree *BinarySearchTree) Contains(x interface{}) (bool, error) {
return tree.contains(x, tree.Root)
}
// 递归查找是否包含某值
func (tree *BinarySearchTree) contains(x interface{}, root *BinaryNode) (bool, error) {
if root == nil {
return false, nil
}
if tree.Comparator == nil {
return false, ErrComparatorIsNil
}
compareResult := tree.Comparator.Compare(x, root)
if compareResult < 0 {
return tree.contains(x, root.Left)
} else if compareResult > 0 {
return tree.contains(x, root.Right)
} else {
return true, nil
}
}
// 递归查找最小值 最小值只能在左子树上,因此只需要递归左子树即可
func (tree *BinarySearchTree) FindMin() (*BinaryNode, error) {
if tree.IsEmpty() {
return nil, ErrTreeIsEmpty
}
return tree.findMin(tree.Root), nil
}
func (tree *BinarySearchTree) findMin(root *BinaryNode) *BinaryNode {
if root == nil {
return nil
} else if root.Left == nil {
return root
}
return tree.findMin(root.Left)
}
// 使用非递归的方式查找最大值 最大值只能在右子树上的最后的叶子节点
func (tree *BinarySearchTree) FindMax() (*BinaryNode, error) {
if tree.IsEmpty() {
return nil, ErrTreeIsEmpty
}
root := tree.Root
for ; root.Right != nil; {
root = root.Right
}
return root, nil
}
// 插入值val 同contains方法一样遍历树,如果找到相同的值不做任何操作,如果比当前节点值大,递归其插入左子树,否则插入又子树
func (tree *BinarySearchTree) Insert(val interface{}) {
tree.Root = tree.insert(val, tree.Root)
}
func (tree *BinarySearchTree) insert(val interface{}, root *BinaryNode) *BinaryNode {
if root == nil {
return &BinaryNode{val, nil, nil}
}
compareResult := tree.Comparator.Compare(val, root)
if compareResult < 0 {
root.Left = tree.insert(val, root.Left)
} else if compareResult > 0 {
root.Right = tree.insert(val, root.Right)
} else {
//重复值,不做操作
}
return root
}
// 删除操作最为复杂
// 先递归查找到要删除的元素
// 然后分为:叶子节点,左子树为nil,右子树为nil,左右均不为nil四种情况
func (tree *BinarySearchTree) Remove(val interface{}) *BinaryNode {
return tree.remove(val, tree.Root, nil)
}
func (tree *BinarySearchTree) remove(val interface{}, root, parent *BinaryNode) (*BinaryNode) {
if root == nil {
return nil
}
compareResult := tree.Comparator.Compare(val, root)
if compareResult < 0 {
return tree.remove(val, root.Left, root)
} else if compareResult > 0 {
return tree.remove(val, root.Right, root)
} else {
ret := &BinaryNode{Val: root.Val}
// 左右子树有任意一个为空,用另外一个替换掉当前节点即可
if root.Left == nil {
tree.replaceChild(parent, val, root.Right)
return ret
}
if root.Right == nil {
tree.replaceChild(parent, val, root.Left)
return ret
}
// 左右子树均不为空,则将右子树中的最小值替换当前节点,并从又子树中删掉该最小值即可
rightMin := tree.findMin(root.Right)
root.Val = rightMin.Val
tree.replaceChild(root.Right, rightMin.Val, rightMin.Right)
return ret
}
}
// 给定的值是左子节点的值,则替换左节点,否则替换右节点
func (tree *BinarySearchTree) replaceChild(parent *BinaryNode, oldVal interface{}, theNode *BinaryNode) {
if parent == nil {
return
}
if tree.Comparator.Compare(oldVal, parent.Left) == 0 {
parent.Left = theNode
} else {
parent.Right = theNode
}
}
// 层序遍历输出
func (tree *BinarySearchTree) Print() {
if tree.IsEmpty() {
return
}
// 使用go官方包里的list模拟队列的操作
l := list.New()
l.PushBack(tree.Root)
for ; l.Len() > 0; {
element := l.Front()
l.Remove(element)
if node, ok := element.Value.(*BinaryNode); ok && node != nil {
l.PushBack(node.Left)
l.PushBack(node.Right)
fmt.Printf("%v\t", node.Val)
}
}
}
-------------------------------------binarysearchtree_test.go-------------------------------------package binarysearchtree
import (
"testing"
"fmt"
)
type IntComparator struct {
}
func (this IntComparator) Compare(x interface{}, y *BinaryNode) int {
if y == nil {
if x == nil {
return 0
} else {
return 1
}
}
if x == nil {
return -1
}
return x.(int) - y.Val.(int)
}
func TestBinarySearchTree(t *testing.T) {
tree := New(IntComparator{})
tree.Insert(6)
tree.Insert(2)
tree.Insert(8)
tree.Insert(1)
tree.Insert(4)
tree.Insert(3)
tree.Remove(2)
fmt.Println(tree.Contains(4))
tree.Print()
}
package binarysearchtree
import (
"fmt"
"container/list"
"errors"
)
var (
ErrComparatorIsNil = errors.New("comparator of BinarySearchTree is nil")
ErrTreeIsEmpty = errors.New("BinarySearchTree is empty")
)
type (
Comparator interface {
Compare(x interface{}, y *BinaryNode) int
}
BinaryNode struct {
Val interface{}
Left, Right *BinaryNode
}
BinarySearchTree struct {
Root *BinaryNode
Comparator Comparator
}
)
// 创建二叉搜索树时必须提供排序规则
func New(comparator Comparator) *BinarySearchTree {
if comparator == nil {
panic(ErrComparatorIsNil)
}
return &BinarySearchTree{nil, comparator}
}
// 清空数据
func (tree *BinarySearchTree) MakeEmpty() {
tree.Root = nil
}
func (tree *BinarySearchTree) IsEmpty() bool {
return tree.Root == nil
}
func (tree *BinarySearchTree) Contains(x interface{}) (bool, error) {
return tree.contains(x, tree.Root)
}
// 递归查找是否包含某值
func (tree *BinarySearchTree) contains(x interface{}, root *BinaryNode) (bool, error) {
if root == nil {
return false, nil
}
if tree.Comparator == nil {
return false, ErrComparatorIsNil
}
compareResult := tree.Comparator.Compare(x, root)
if compareResult < 0 {
return tree.contains(x, root.Left)
} else if compareResult > 0 {
return tree.contains(x, root.Right)
} else {
return true, nil
}
}
// 递归查找最小值 最小值只能在左子树上,因此只需要递归左子树即可
func (tree *BinarySearchTree) FindMin() (*BinaryNode, error) {
if tree.IsEmpty() {
return nil, ErrTreeIsEmpty
}
return tree.findMin(tree.Root), nil
}
func (tree *BinarySearchTree) findMin(root *BinaryNode) *BinaryNode {
if root == nil {
return nil
} else if root.Left == nil {
return root
}
return tree.findMin(root.Left)
}
// 使用非递归的方式查找最大值 最大值只能在右子树上的最后的叶子节点
func (tree *BinarySearchTree) FindMax() (*BinaryNode, error) {
if tree.IsEmpty() {
return nil, ErrTreeIsEmpty
}
root := tree.Root
for ; root.Right != nil; {
root = root.Right
}
return root, nil
}
// 插入值val 同contains方法一样遍历树,如果找到相同的值不做任何操作,如果比当前节点值大,递归其插入左子树,否则插入又子树
func (tree *BinarySearchTree) Insert(val interface{}) {
tree.Root = tree.insert(val, tree.Root)
}
func (tree *BinarySearchTree) insert(val interface{}, root *BinaryNode) *BinaryNode {
if root == nil {
return &BinaryNode{val, nil, nil}
}
compareResult := tree.Comparator.Compare(val, root)
if compareResult < 0 {
root.Left = tree.insert(val, root.Left)
} else if compareResult > 0 {
root.Right = tree.insert(val, root.Right)
} else {
//重复值,不做操作
}
return root
}
// 删除操作最为复杂
// 先递归查找到要删除的元素
// 然后分为:叶子节点,左子树为nil,右子树为nil,左右均不为nil四种情况
func (tree *BinarySearchTree) Remove(val interface{}) *BinaryNode {
return tree.remove(val, tree.Root, nil)
}
func (tree *BinarySearchTree) remove(val interface{}, root, parent *BinaryNode) (*BinaryNode) {
if root == nil {
return nil
}
compareResult := tree.Comparator.Compare(val, root)
if compareResult < 0 {
return tree.remove(val, root.Left, root)
} else if compareResult > 0 {
return tree.remove(val, root.Right, root)
} else {
ret := &BinaryNode{Val: root.Val}
// 左右子树有任意一个为空,用另外一个替换掉当前节点即可
if root.Left == nil {
tree.replaceChild(parent, val, root.Right)
return ret
}
if root.Right == nil {
tree.replaceChild(parent, val, root.Left)
return ret
}
// 左右子树均不为空,则将右子树中的最小值替换当前节点,并从又子树中删掉该最小值即可
rightMin := tree.findMin(root.Right)
root.Val = rightMin.Val
tree.replaceChild(root.Right, rightMin.Val, rightMin.Right)
return ret
}
}
// 给定的值是左子节点的值,则替换左节点,否则替换右节点
func (tree *BinarySearchTree) replaceChild(parent *BinaryNode, oldVal interface{}, theNode *BinaryNode) {
if parent == nil {
return
}
if tree.Comparator.Compare(oldVal, parent.Left) == 0 {
parent.Left = theNode
} else {
parent.Right = theNode
}
}
// 层序遍历输出
func (tree *BinarySearchTree) Print() {
if tree.IsEmpty() {
return
}
// 使用go官方包里的list模拟队列的操作
l := list.New()
l.PushBack(tree.Root)
for ; l.Len() > 0; {
element := l.Front()
l.Remove(element)
if node, ok := element.Value.(*BinaryNode); ok && node != nil {
l.PushBack(node.Left)
l.PushBack(node.Right)
fmt.Printf("%v\t", node.Val)
}
}
}
-------------------------------------binarysearchtree_test.go-------------------------------------package binarysearchtree
import (
"testing"
"fmt"
)
type IntComparator struct {
}
func (this IntComparator) Compare(x interface{}, y *BinaryNode) int {
if y == nil {
if x == nil {
return 0
} else {
return 1
}
}
if x == nil {
return -1
}
return x.(int) - y.Val.(int)
}
func TestBinarySearchTree(t *testing.T) {
tree := New(IntComparator{})
tree.Insert(6)
tree.Insert(2)
tree.Insert(8)
tree.Insert(1)
tree.Insert(4)
tree.Insert(3)
tree.Remove(2)
fmt.Println(tree.Contains(4))
tree.Print()
}
相关文章推荐
- 二叉查找树的游标实现
- 请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。
- 200行Go代码实现一个区块链之二——区块生成与网络通信
- 类模板实现二叉查找树
- 二叉查找树 BinarySearchTree 的实现
- 【Go web开发之revel+mgo】第4章 实现评论功能
- 二叉查找树的实现——C++
- Go实现集合set
- 二叉查找树的实现(可执行代码)
- go-mysql-elasticsearch实现mysql 与elasticsearch实时同步深入详解
- 【寒江雪】Go实现单例模式
- Go语言如何实现遗传算法
- 深入解析Go中Slice底层实现
- go: 一个通用log模块的实现
- 用go实现web日志分析及网页挂马关键字检测
- 数据结构实现之有序符号表BST二叉查找树
- Go语言有缓冲和无缓冲通道实现样例
- Go -- 实现二叉搜索树
- C++二叉查找树实现过程详解
- 最优二叉查找树-optimal-BST--C++实现