BinarySearchTree

package SortedMap

import (
	"fmt"
	"testing"
)

/*
搜索二叉树
搜索二叉树一定要说明以什么标准来排序
经典的搜索二叉树,树上没有重复的用来排序的key值
如果有重复节点的需求,可以在一个节点内部增加数据项,便于平衡性调整

链接重复值的节点,不便于平衡性调整

经典的搜索二叉树:
任何一个节点为头的树,左边的子树都比头节点要小,右边的子树都比头节点要大,且树上没有重复值
*/

/*
搜索二叉树查询key (查询某个key存在还是不存在)
1. 如果当前节点的value == key, 返回true
2. 如果当前节点的value < key , 当前节点向左移动
3. 如果当前节点的value > key , 当前节点向右移动
4. 如果当前节点变成nil, 返回false


搜索二叉树自己的增删查,也不是很容易
一、查:从头节点开始,比当前节点小,往左滑,比当前节点大,往右滑,Value相等时,返回,越界时即不存在
二、改:删了再加
三、增:从头节点开始,比当前节点小,往左滑,比当前节点大,往右滑,滑到空的时候,添加
四、删:分为几种情况
   1> 找不到,不用删
   2> 找到,一定是具体的节点,节点分为多种情况
      1.无左孩子,无右孩子  直接删
      2.有右孩子,无左孩子  右孩子提拔上来
      3.有左孩子,无右孩子  左孩子提拔上来
      4.有左孩子,有右孩子  用后继节点(右树上的最左节点)替代当前环境    Right.Left.Left....
            若Right.Left.Left....有右孩子,则把其右孩子给右孩子父节点的父节点,作为其左孩子


                   5
                /    \
               S     10
                    /  \
                   8   ...
                  /
                 6
                  \
                   T <--------


                   5
                /    \
               S     10
                    /  \
                   8   ...
                  /
                 T <--------




删除时的两种情况
情况1

                   d      <- 要删的节点
                /    \
               s      r
                    /  \
                   a    f
                  /
                 b       <-  successorNode.Parent != deleteNode
                  \
                   T


                   b
                /    \
               s      r
                    /  \
                   a    f
                  /
                 T


情况2
                  a   <- 要删除节点
                   \
                    b
                  /  \
                nil   c
                       \
                        s

                    b
                  /  \
                nil   c
                       \
                        s


		successorNode := getMinimum(deleteNode.Right)                    // 找到后继节点

		if successorNode.Parent != deleteNode {                          // 边界考虑   后继节点离 将被删除的节点有一定距离
			ABSTree.transplant(successorNode, successorNode.Right)
			successorNode.Right = deleteNode.Right
			successorNode.Right.Parent = successorNode
		}

		ABSTree.transplant(deleteNode, successorNode)
		successorNode.Left = deleteNode.Left
		successorNode.Left.Parent = successorNode
		nodeToReturn = successorNode
区分两种情况
*/

type Node struct {
	Value interface {
		Compare(v interface{}) int
	}
	Parent *Node
	Left   *Node
	Right  *Node
}

func CreateNode(value interface{ Compare(v interface{}) int }, parent *Node, left *Node, right *Node) *Node {
	return &Node{
		Value:  value,
		Parent: parent,
		Left:   left,
		Right:  right,
	}
}

type AbstractBinarySearchTree struct {
	Root *Node //Root 整棵树的开始节点
	Size int   //Size 树的大小
}

func CreateAbstractBinarySearchTree() *AbstractBinarySearchTree {
	return &AbstractBinarySearchTree{}
}

func (ABSTree *AbstractBinarySearchTree) search(element interface{ Compare(v interface{}) int }) *Node {
	node := ABSTree.Root
	for node != nil && node.Value != nil && node.Value != element {
		if element.Compare(node.Value) < 0 { // element < node.Value
			node = node.Left
		} else {
			node = node.Right
		}
	} // 小于 左滑,  大于 有滑
	return node
}

func (ABSTree *AbstractBinarySearchTree) insert(element interface{ Compare(v interface{}) int }) *Node {
	if ABSTree.Root == nil { //头是空的,直接添加,作为头
		ABSTree.Root = CreateNode(element, nil, nil, nil)
		ABSTree.Size++
		return ABSTree.Root
	}

	insertParentNode := (*Node)(nil)                           // 插在哪个节点下
	searchTempNode := ABSTree.Root                             // 从根上遍历
	for searchTempNode != nil && searchTempNode.Value != nil { // 找到插入节点的父节点
		insertParentNode = searchTempNode
		if element.Compare(searchTempNode.Value) < 0 { // 小于 左滑
			searchTempNode = searchTempNode.Left
		} else { // 大于 右滑
			searchTempNode = searchTempNode.Right
		}
	}

	newNode := CreateNode(element, insertParentNode, nil, nil) // 创建刚好指向找到的父节点的节点
	if insertParentNode.Value.Compare(newNode.Value) > 0 {     // 父节点的值比 插入节点的大
		insertParentNode.Left = newNode // 插入左孩子
	} else { // 插入右孩子
		insertParentNode.Right = newNode
	}
	ABSTree.Size++ //树的大小自增
	return newNode
}

func (ABSTree *AbstractBinarySearchTree) delete(element interface{ Compare(v interface{}) int }) *Node {
	deleteNode := ABSTree.search(element) // 查找要删除的节点是否存在,不存在直接返回
	if deleteNode != nil {                // 存在则删除
		return ABSTree.deleteNode(deleteNode)
	}
	return nil
}

// 做自平衡的时候,会用到deleteNode方法
func (ABSTree *AbstractBinarySearchTree) deleteNode(deleteNode *Node) *Node {  // 返回的不是删掉的节点,谁接替了被删除节点环境,就返回谁,新上来的那玩意返回
	if deleteNode == nil {
		return nil
	}

	nodeToReturn := (*Node)(nil)
	if deleteNode.Left == nil {
		// transplant(a,b) b 去替换a的环境, a断掉链接,把b返回
		nodeToReturn = ABSTree.transplant(deleteNode, deleteNode.Right)  // 拿右孩子替代当前环境
	} else if deleteNode.Right == nil {
		nodeToReturn = ABSTree.transplant(deleteNode, deleteNode.Left)   // 拿左孩子替代当前环境
	} else {
		successorNode := getMinimum(deleteNode.Right)                    // 找到后继节点

		if successorNode.Parent != deleteNode {                          // 边界考虑   后继节点离 将被删除的节点有一定距离
			ABSTree.transplant(successorNode, successorNode.Right)       // 后继节点拿有孩子去替换后继节点的环境
			successorNode.Right = deleteNode.Right                       // 后继节点的右指针 接管删除节点的右孩子
			successorNode.Right.Parent = successorNode                   // 右孩子的父指针,指向自己
		}

		ABSTree.transplant(deleteNode, successorNode)
		successorNode.Left = deleteNode.Left
		successorNode.Left.Parent = successorNode
		nodeToReturn = successorNode
	}
	ABSTree.Size--

	return nodeToReturn
}

func (ABSTree *AbstractBinarySearchTree) transplant(nodeToReplace, newNode *Node) *Node {
	if nodeToReplace.Parent == nil {
		ABSTree.Root = newNode
	} else if nodeToReplace == nodeToReplace.Parent.Left {
		nodeToReplace.Parent.Left = newNode
	} else {
		nodeToReplace.Parent.Right = newNode
	}
	if newNode != nil {
		newNode.Parent = nodeToReplace.Parent
	}
	return newNode
}

func (ABSTree *AbstractBinarySearchTree) contains(element interface{ Compare(v interface{}) int }) bool {
	return ABSTree.search(element) != nil
}

func (ABSTree *AbstractBinarySearchTree) getMinimum() interface{ Compare(v interface{}) int } {
	return getMinimum(ABSTree.Root).Value
}
func (ABSTree *AbstractBinarySearchTree) getMaximum() interface{ Compare(v interface{}) int } {
	return getMaximum(ABSTree.Root).Value
}

func (ABSTree *AbstractBinarySearchTree) getSuccessor(element interface{ Compare(v interface{}) int }) interface{ Compare(v interface{}) int } {
	return getSuccessor(ABSTree.search(element)).Value
}

func (ABSTree *AbstractBinarySearchTree) getSize() int {
	return ABSTree.Size
}

func (ABSTree *AbstractBinarySearchTree) printTreeInOrder() {
	printTreeInOrder(ABSTree.Root)
}

func (ABSTree *AbstractBinarySearchTree) printTreePreOrder() {
	printTreePreOrder(ABSTree.Root)
}

func (ABSTree *AbstractBinarySearchTree) printTreePostOrder() {
	printTreePostOrder(ABSTree.Root)
}

func printTreeInOrder(entry *Node) {
	if entry != nil {
		printTreeInOrder(entry.Left)
		if entry.Value != nil {
			fmt.Println(entry.Value)
		}
		printTreeInOrder(entry.Right)
	}
}

func printTreePreOrder(entry *Node) {
	if entry != nil {
		if entry.Value != nil {
			fmt.Println(entry.Value)
		}
		printTreeInOrder(entry.Left)
		printTreeInOrder(entry.Right)
	}
}

func printTreePostOrder(entry *Node) {
	if entry != nil {
		printTreeInOrder(entry.Left)
		printTreeInOrder(entry.Right)
		if entry.Value != nil {
			fmt.Println(entry.Value)
		}
	}
}

func getMinimum(node *Node) *Node {
	for node.Left != nil {
		node = node.Left
	}
	return node
}

func getMaximum(node *Node) *Node {
	for node.Right != nil {
		node = node.Right
	}
	return node
}

func getSuccessor(node *Node) *Node {
	if node.Right != nil {
		return getMinimum(node.Right)
	} else {
		currentNode := node
		parentNode := node.Parent
		for parentNode != nil && currentNode == parentNode.Right {
			currentNode = parentNode
			parentNode = parentNode.Parent
		}
		return parentNode
	}
}

func (ABSTree *AbstractBinarySearchTree) printTree() {
	ABSTree.printSubTree(ABSTree.Root)
}

func (ABSTree *AbstractBinarySearchTree) printSubTree(node *Node) {
	if node.Right != nil {
		PrintTree(node.Right, true, " ")
	}
	printNodeValue(node)
	if node.Left != nil {
		PrintTree(node.Left, false, " ")
	}
}

func PrintTree(node *Node, isRight bool, indent string) {
	if node.Right != nil {
		if isRight {
			indent += "      "
		} else {
			indent += " |     "
		}
		PrintTree(node.Right, true, indent)
	}
	fmt.Print(indent)
	if isRight {
		fmt.Print(" /")
	} else {
		fmt.Print(" \\")
	}
	fmt.Print("----- ")
	printNodeValue(node)
	if node.Left != nil {
		if isRight {
			indent += " |     "
		} else {
			indent += "      "
		}
		PrintTree(node.Left, false, indent)
	}
}

func printNodeValue(node *Node) {
	if node.Value == nil {
		fmt.Print("<nil>")
	} else {
		fmt.Print(node.Value)
	}
	fmt.Println()
}

func (node *Node) isLeaf() bool {
	return node.Left == nil && node.Right == nil
}

type Value struct {
	val int
}

func (v Value) Compare(value interface{}) int {
	return v.val - value.(*Value).val
}
func TestAbstractBinarySearchTree(t *testing.T) {
	v1 := &Value{100}
	v2 := &Value{201}
	v3 := &Value{1}
	v4 := &Value{20}
	v5 := &Value{19}
	v6 := &Value{1999}
	v7 := &Value{21}

	abstree := CreateAbstractBinarySearchTree()
	abstree.insert(v1)
	abstree.insert(v2)
	abstree.insert(v3)
	abstree.insert(v4)
	abstree.insert(v5)
	abstree.insert(v6)
	abstree.insert(v7)

	//abstree.delete(v3)

	abstree.printTree()
	abstree.printTreePreOrder()

}

/*
裸的二叉搜索树特别不讲究
1.基础的二叉搜索树,添加、删除时候不照顾平衡性
2.数据状况很差时,性能就很差
输入状况决定性能
裸二叉搜索树:1,2,3,4,5 这种插入情况 O(N)


广义上平衡性:任何节点左右树规模差不多,高度收敛于logN N是整个节点个数
严格定义:任何节点左右树高度差不大于1

引入自动平衡的机制,自平衡的代价不能超过logN,做完平衡之后,
树上的插入删除操作都能做到O(logN),这种具有平衡性质的二叉树叫做:平衡搜索二叉树

平衡搜索二叉树种类很多:红黑树算是很难的一个

给二叉搜索树引入两个动作: 左旋、右旋

左旋右旋,动作对头节点来说
对哪个节点实行左旋右旋,  右旋:以某个节点向右倒下去

              a
            /   \
           b     T
         /  \
        c    S
      /  \
     甲   乙


    对a节点进行右旋,对谁进行右旋,谁就倒向右侧,对谁进行左旋,谁就倒向左侧
    提拔左孩子上来,s给a的左

               b
            /    \
           c      a
         /   \  /   \
        甲   乙 s     T



------------------------------------------

               a
            /    \
           s      b
                /   \
               T     c
                   /   \
                  甲    乙
       对a左旋, T给a

                  b
                /   \
              a      c
            /  \   /   \
           s    T 甲    乙
*/

// 增加左旋右旋动作的搜索二叉树
type AbstractSelfBalancingBinaryTree struct {
	AbstractBinarySearchTree
}

func (ASBBTree *AbstractSelfBalancingBinaryTree) rotateLeft(node *Node) *Node {
	temp := node.Right
	temp.Parent = node.Parent

	node.Right = temp.Left
	if node.Right != nil {
		node.Right.Parent = node
	}

	temp.Left = node
	node.Parent = temp

	if temp.Parent != nil {
		if node == temp.Parent.Left {
			temp.Parent.Left = temp
		} else {
			temp.Parent.Right = temp
		}
	} else {
		ASBBTree.Root = temp
	}
	return temp
}

func (ASBBTree *AbstractSelfBalancingBinaryTree) rotateRight(node *Node) *Node {
	temp := node.Left
	temp.Parent = node.Parent

	node.Left = temp.Right
	if node.Left != nil {
		node.Left.Parent = node
	}

	temp.Right = node
	node.Parent = temp

	if temp.Parent != nil {
		if node == temp.Parent.Left {
			temp.Parent.Left = temp
		} else {
			temp.Parent.Right = temp
		}
	} else {
		ASBBTree.Root = temp
	}
	return temp
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

metabit

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值