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
}
BinarySearchTree
最新推荐文章于 2022-03-02 00:17:08 发布