Go实现二叉查找树

—————————————–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()
}

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/luopotaotao/article/details/79362349
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞