红黑树--Golang实现

红黑树Golang实现

1、红黑树简介

1.1 什么是红黑树

红黑树是树的数据结构中最为重要的一种。Java的容器TreeSet、TreeMap均使用红黑树实现。JDK1.8中HashMap中也加入了红黑树。C++ STL中的map和set同样使用红黑树实现。之前的文章已经详细介绍了2-3-4树的性质与操作。本篇文章将从2-3-4树与红黑树关系出发,详细阐明红黑树。   2-3-4树和红黑树是完全等价的,但是2-3-4树的编程实现相对复杂,所以一般是通过实现红黑树来实现替代2-3-4树,而红黑树也同样保证在O(logN)的时间内完成查找、插入和删除操作。

1.2 红黑树的性质

红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:

  1. 节点是红色或黑色。
  2. 根节点是黑色。
  3. 每个叶节点(这里的叶节点是指NULL节点,在《算法导论》中这个节点叫哨兵节点,除了颜色属性外,其他属性值都为任意。为了和以前的叶子节点做区分,原来的叶子节点还叫叶子节点,这个节点就叫他NULL节点吧)是黑色的。
  4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点,或者理解为红节点不能有红孩子)
  5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点(黑节点的数目称为黑高black-height)。

正是红黑树的这5条性质,使一棵n个结点的红黑树始终保持了logn的高度,从而也就解释了上面所说的“红黑树的查找、插入、删除的时间复杂度最坏为O(log n)”这一结论成立的原因

通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。

红黑树虽然本质上是一棵二叉查找树,但它在二叉查找树的基础上增加了着色和相关的性质使得红黑树相对平衡,从而保证了红黑树的查找、插入、删除的时间复杂度最坏为O(log n)。

1.3 红黑树和2-3-4树的等价关系

如果一棵树满足红黑树,把红色节点收缩到其父节点,就变成了2-3-4树,所有红色节点都与其父节点构成3或4节点,其它节点为2节点。一颗红黑树对应唯一形态的2-3-4树,但是一颗2-3-4树可以对应多种形态的红黑树(主要是3节点可以对应两种不同的红黑树形态)。a7eb2cfd021df9468dbb532ab7d0b9ca

1.4 定义节点名称:

  • 父节点——P(Parent)
  • 祖父节点——G(GrandParent)
  • 叔叔节点——U(Uncle)
  • 当前节点——C(Current)
  • 兄弟节点——B(Brother)
  • 左孩子——L(Left)
  • 右孩子——R(Right)

2、红黑树查找

与二叉树查找一致,不再赘述

3、红黑树插入

红黑树首先是一棵二叉排序树,所以它的插入操作要遵循二叉排序树的插入原则。

3.1 插入节点的父节点(P)为黑色

  1. 直接将插入涂红
  2. 插入结束

3.2 插入节点的父节点(P)为红色,叔叔节点(U)为黑色

若待插入节点的父节点为红色,叔叔节点为黑色,此种情形又需要区分节点的插入位置,根据插入位置的不同进行相应的调整。此种情形共有四种:

3.2.1 父节点(P)是左孩子,插入节点(C)是左孩子

  1. 以祖父节点(G)为中心,右旋

  2. 父节点(P)涂黑,祖父节点(G)涂红

  3. 插入结束

682dc1b7a17f89bf053c205a01ae22eb

682dc1b7a17f89bf053c205a01ae22eb

3.2.2 父节点(P)为左孩子,插入节点(C)为右孩子

  1. 父节点(P)为中心,左旋
  2. 祖父节点(G)为中心,右旋
  3. 插入节点(C)涂黑,祖父节点(G)涂红
  4. 插入结束

45bb986e2a80000741dbbcfcbad95d98

feb2094579ddc59fb4ae65c000569d86

3.2.3 父节点(P)为右孩子,插入节点(C)为右孩子

  1. 祖父节点(G)左旋
  2. 父节点(P)涂黑
  3. 祖父节点(G)涂红
  4. 插入结束

7b196277097b9b465f96234acc954464

e6580f71961c09379716df3413fc40eb

3.2.4 父节点(P)为右孩子,插入节点(C)为左孩子

  1. 父节点(P)为中心,右旋
  2. 祖父节点(G)为中心,左旋
  3. 当前节点(C)涂黑
  4. 祖父节点(G)涂红
  5. 插入结束

ef756e14d1666d956e4e5f41cbc05f57

5aa7bac42c17f0b7f2e623ae41b480ac

3.3 父节点(P)为红色,叔叔节点(U)为红色

当前节点(C)为左子树或者右子树都是一套流程:

  1. 祖父节点(G)涂红
  2. 父亲节点(P)涂黑
  3. 叔叔节点(U)涂黑
  4. 将祖父节点(G)作为新插入点回溯
  5. 插入完成

900d4e155438a4a889310a4cec6fa2bb

4、红黑树删除

4.1 删除节点(D)为红色且是叶子节点

红色叶子节点(D)的父节点(P)必然是黑色,直接删除D即可

  1. 删除当前节点(D)
  2. 删除完毕

4.2 删除节点(D)为红色,且只有左子树或者右子树

违背红黑树性质,所以不存在这种情况

e5c6ef00c43e6aff1d839472139e20eb

4.3 删除节点(D)为红色,且既有左子树又有右子树

用删除节点(D)的后继节点替换(只进行数据替换即可,颜色不变,此时也不需要调整结构),然后删除后继节点,后继节点的删除同样要遵循红黑树的删除过程

4.4 删除节点(D)为黑色,且仅有左子树或仅有右子树

不存在左(右)孩子为红色因为违背了性质5

  1. 使用左(右)孩子(DL/DR)替换 删除节点(D)
  2. 将左(右)孩子(DL/DR)涂黑

图中填充为绿色的节点代表既可以是红色也可以是黑色,下同。

a16e409e84af6de2f90ae1b9459723d1

4.5 删除节点(D)为黑色,且为叶子节点

黑色叶子节点(D)的删除分为两步骤,节点调整以及删除应当先调整节点之间的关系,再执行删除操作(仅有部分情形将会结束调整,而执行删除操作)。

4.5.1 删除节点(D)为左孩子,兄弟节点为红色

  1. 交换父节点(P)与兄弟节点(B)的颜色
  2. 以父节点(P)为中心,左旋
  3. 左旋结束以后此时D的兄弟节点将变成黑色,可以继续调整(不急着删除)

ae996e76320a6d03f1778d28046db6d1

ae6a2f79ac618b07742cf0b9c1222c11

4.5.2 删除节点(D)为右孩子,兄弟节点(B)为红色

与4.5.2类似

  1. 交换父节点(P)与兄弟节点(B)的颜色
  2. 以父节点(P)为中心,右旋
  3. 右旋结束以后此时D的兄弟节点将变成黑色,可以继续调整(不急着删除)

11e922e21e3f9845df5bc356b3c14a35

add5f1578e883505534e521e9ed48187

4.5.3【有删除操作】 删除节点(D)为左孩子,兄弟节点(B)为黑色,远侄子节点(BR)为红色

  1. 交换父亲节点(P)与兄弟节点(B)的颜色
  2. 以父亲节点为中心,左旋
  3. 远侄子节点(BR),涂黑
  4. 执行删除操作

4.5.4 【有删除操作】删除节点(D)为右孩子,兄弟节点(B)为黑色,远侄子节点(BL)为红色

  1. 交换父亲节点(P)与兄弟节点(B)的颜色
  2. 以父亲节点为中心,左旋
  3. 远侄子节点(BR),涂黑
  4. 执行删除操作

显然,这两个概念相同所以给出一份图解即可

768d048844c4ee025f634e98ac77d296

40ab6f396ac521e479a5a57fb82e8cbe

4.5.5 删除节点(D)为左孩子,兄弟节点(B)为黑色,远侄子节点(BR)为黑色,近侄子节点(BL)为红色

  1. 交换兄弟节点(B)与近侄子节点(BL)的颜色
  2. 以兄弟节点(B)为中心,右旋
  3. 此时删除节点(D)将作为当前节点(C)继续参与调整而不执行删除(变形成:4.5.3 删除节点(D)为左孩子,兄弟节点(B)为黑色,远侄子节点(BR)为红色

4.5.6 删除节点(D)为右孩子,兄弟节点(B)为黑色,远侄子节点(BL)为黑色,近侄子节点(BR)为红色

  1. 交换兄弟节点(B)与近侄子节点(BR)的颜色
  2. 以兄弟节点(B)为中心,左旋
  3. 此时删除节点(D)将作为当前节点(C)继续参与调整而不执行删除(变形成:4.5.4删除节点(D)为右孩子,兄弟节点(B)为黑色,远侄子节点(BL)为红色

显然,这两种情形概念相同,所以给出一份图解即可

c18d55f6e6edc08d07058e305505104a

8909e159a1a84070577e2b439ac35d01

5fa8defa30b2a48ae4eb6e49dde5fbe2

4.5.7 【有删除操作】父亲节点(P)为红色,兄弟节点(B)以及B的孩子(BL/BR)均为黑色

  1. 父亲节点(P)涂黑
  2. 兄弟节点(B)涂红
  3. 执行删除

b24dfb1708dcc9132b3a5c359fc188e4

4.5.8 父亲节点(P),兄弟节点(B)以及B的孩子(BL/BR)均为黑色

  1. 兄弟节点(B)涂红
  2. 将父亲节点(P)继续参与调整 直至参与调整的节点为root节点 或 被执行删除操作

b3e5e1215eda69b0f6331f7c9a65ad88

5、总结

红黑树是数据结构最为重要的一种树形结构,其应用场景也是十分广泛。牢记红黑树的5条性质最为重要

  1. 节点是红色或黑色。
  2. 根节点是黑色。
  3. 每个叶节点(这里的叶节点是指NULL节点,在《算法导论》中这个节点叫哨兵节点,除了颜色属性外,其他属性值都为任意。为了和以前的叶子节点做区分,原来的叶子节点还叫叶子节点,这个节点就叫他NULL节点吧)是黑色的。
  4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点,或者理解为红节点不能有红孩子)
  5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点(黑节点的数目称为黑高black-height)。

6、代码

package red_black_tree

import (
    "errors"
    "fmt"
    "github.com/Ccheers/temp_test/my_data_struct_and_algorithms/tree"
    "math"
    "strconv"
    "strings"
    "sync"
)

type RedBlackFlag bool

const (
    _RED   RedBlackFlag = true
    _BLACK RedBlackFlag = false
)

//(1)节点是要么红色或要么是黑色。
//(2)根一定是黑色节点。
//(3)每个叶子节点都带有两个空的黑色节点(称之为NIL节点,它又被称为黑哨兵)。
//(4)每个红色节点的两个子节点都是黑色(或者说从每个叶子到根的所有路径上不能有两个连续的红色节点)。
//(5)从任一节点到它所能到达得叶子节点的所有简单路径都包含相同数目的黑色节点。
type RedBlackTree struct {
    root *redBlackTreeNode
}

func (t *RedBlackTree) Insert(node *redBlackTreeNode) *RedBlackTree {
    if t.root == nil {
        node.SetFlag(_BLACK)
        node.SetIndex(tree.ROOT)
        t.root = node
    } else {
        t.root.insert(node)
        fixBalance(node)
        t.root = t.root.findRoot()
    }
    return t
}
func (t *RedBlackTree) Search(data interface{}) (*redBlackTreeNode, error) {
    node := NewRedBlackTreeNode(data)
    return t.root.search(node)
}
func (t *RedBlackTree) Delete(data interface{}) error {
    node := NewRedBlackTreeNode(data)
    node, err := t.root.search(node)
    if err != nil {
        return err
    }
    deleteNode(node)
    return nil
}

type redBlackTreeNode struct {
    index                               tree.ChildrenIndex
    depth                               int
    parent, leftChildren, rightChildren *redBlackTreeNode //leftChild:0, rightChild:1, parent:2
    flag                                RedBlackFlag
    
    data  interface{}
    mutex sync.RWMutex
}

func (r *redBlackTreeNode) Depth() int {
    return r.depth
}

func (r *redBlackTreeNode) SetDepth(depth int) {
    r.depth = depth
}

func (r *redBlackTreeNode) Index() tree.ChildrenIndex {
    return r.index
}

func (r *redBlackTreeNode) SetIndex(index tree.ChildrenIndex) {
    r.index = index
}

func (r *redBlackTreeNode) Flag() RedBlackFlag {
    return r.flag
}

func (r *redBlackTreeNode) SetFlag(flag RedBlackFlag) {
    r.flag = flag
}

func (r *redBlackTreeNode) setRightChildren(node *redBlackTreeNode) *redBlackTreeNode {
    r.rightChildren = node
    return r
}
func (r *redBlackTreeNode) getRightChildren() *redBlackTreeNode {
    return r.rightChildren
}

func (r *redBlackTreeNode) setLeftChildren(node *redBlackTreeNode) *redBlackTreeNode {
    r.leftChildren = node
    return r
}
func (r *redBlackTreeNode) getLeftChildren() *redBlackTreeNode {
    return r.leftChildren
}

func (r *redBlackTreeNode) setParent(node *redBlackTreeNode) *redBlackTreeNode {
    r.parent = node
    return r
}
func (r *redBlackTreeNode) getParent() *redBlackTreeNode {
    return r.parent
}

func (r *redBlackTreeNode) compare(treeNode *redBlackTreeNode) tree.CompareType {
    if treeNode.data.(int) == r.data.(int) {
        return tree.EQUAL
    }
    if treeNode.data.(int) > r.data.(int) {
        return tree.GREATER
    } else {
        return tree.LESS
    }
}

func (r *redBlackTreeNode) insert(node *redBlackTreeNode) {
    //defer r.updateDepth()
    switch r.compare(node) {
    case tree.EQUAL:
        return
    case tree.GREATER:
        if r.getRightChildren().data != nil {
            r.getRightChildren().insert(node)
        } else {
            node.setParent(r)
            node.SetIndex(tree.RIGHTCHILDREN)
            r.setRightChildren(node)
        }
    default:
        if r.getLeftChildren().data != nil {
            r.getLeftChildren().insert(node)
        } else {
            node.setParent(r)
            node.SetIndex(tree.LEFTCHILDREN)
            r.setLeftChildren(node)
        }
    }
}

func (r *redBlackTreeNode) search(data *redBlackTreeNode) (*redBlackTreeNode, error) {
    if r.data == nil {
        return nil, errors.New("not found")
    } else {
        switch r.compare(data) {
        case tree.EQUAL:
            return r, nil
        case tree.GREATER:
            return r.getRightChildren().search(data)
        default:
            return r.getLeftChildren().search(data)
        }
    }
}

func deleteNode(data *redBlackTreeNode) {
    switch true {
    case data.Flag() == _RED && data.isLeaveNode():
        //删除红色叶子节点
        replace(data, &redBlackTreeNode{
            flag: _BLACK,
        })
    case data.Flag() == _RED && data.getLeftChildren().data != nil && data.getRightChildren().data != nil:
        //删除红色节点,既有左子树,又有右子树
        successorNode := data.getRightChildren().findMin()
        data.data = successorNode.data
        deleteNode(successorNode)
    case data.Flag() == _BLACK && data.getLeftChildren().data != nil && data.getRightChildren().data == nil:
        //删除黑色节点只有左子树
        data.getLeftChildren().SetFlag(_BLACK)
        replace(data, data.getLeftChildren())
    case data.Flag() == _BLACK && data.getLeftChildren().data == nil && data.getRightChildren().data != nil:
        //删除黑色节点只有右子树
        data.getRightChildren().SetFlag(_BLACK)
        replace(data, data.getRightChildren())
    case data.Flag() == _BLACK && data.isLeaveNode():
        begin := data
        for begin.getParent() != nil {
            brother := begin.getBrother()
            parent := begin.getParent()
            brotherLeftChildren := brother.getLeftChildren()
            brotherRightChildren := brother.getRightChildren()
            switch true {
            case begin.Index() == tree.LEFTCHILDREN && brother.Flag() == _RED:
                //D为左孩子 B为红色
                swapFlag(parent, brother)
                leftRotate(parent)
                continue
            case begin.Index() == tree.RIGHTCHILDREN && brother.Flag() == _RED:
                //D为右孩子 B为红色
                swapFlag(parent, brother)
                rightRotate(parent)
                continue
            case begin.Index() == tree.LEFTCHILDREN && brother.Flag() == _BLACK && brotherRightChildren.Flag() == _RED:
                //D为左孩子 B为黑色 远侄子节点为红色
                swapFlag(parent, brother)
                leftRotate(parent)
                brotherRightChildren.SetFlag(_BLACK)
                goto deleteNode
            case begin.Index() == tree.RIGHTCHILDREN && brother.Flag() == _BLACK && brotherLeftChildren.Flag() == _RED:
                //D为右孩子 B为黑色 远侄子节点为红色
                swapFlag(parent, brother)
                leftRotate(parent)
                brotherLeftChildren.SetFlag(_BLACK)
                goto deleteNode
            case begin.Index() == tree.LEFTCHILDREN && brother.Flag() == _BLACK && brotherLeftChildren.Flag() == _RED && brotherRightChildren.Flag() == _BLACK:
                //D为左孩子 B为黑色 BL为红色 BR为黑色
                swapFlag(brother, brotherLeftChildren)
                rightRotate(brother)
                continue
            case begin.Index() == tree.RIGHTCHILDREN && brother.Flag() == _BLACK && brotherLeftChildren.Flag() == _BLACK && brotherRightChildren.Flag() == _RED:
                //D为左孩子 B为黑色 BL为黑色 BR为黑色
                swapFlag(brother, brotherRightChildren)
                leftRotate(brother)
                continue
            case parent.Flag() == _RED && brother.Flag() == _BLACK && brotherRightChildren.Flag() == _BLACK && brotherLeftChildren.Flag() == _BLACK:
                //P为红色 B和B的孩子均为黑色
                parent.SetFlag(_BLACK)
                brother.SetFlag(_RED)
                goto deleteNode
            case parent.Flag() == _BLACK && brother.Flag() == _BLACK && brotherRightChildren.Flag() == _BLACK && brotherLeftChildren.Flag() == _BLACK:
                brother.SetFlag(_RED)
                begin = parent
            }
        }
    deleteNode:
        replace(data, &redBlackTreeNode{
            flag: _BLACK,
        })
    }
}
func (r *redBlackTreeNode) isLeaveNode() bool {
    return r.getLeftChildren().data == nil && r.getRightChildren().data == nil
}

func (r *redBlackTreeNode) getBrother() *redBlackTreeNode {
    if r.Index() == tree.LEFTCHILDREN {
        return r.getParent().getRightChildren()
    }
    return r.getParent().getLeftChildren()
}

func swapFlag(node1, node2 *redBlackTreeNode) {
    _f := node1.Flag()
    node1.SetFlag(node2.Flag())
    node2.SetFlag(_f)
}

func replace(currentNode, replaceNode *redBlackTreeNode) {
    
    parent := currentNode.getParent()
    replaceNode.setParent(parent)
    if currentNode.Index() == tree.LEFTCHILDREN {
        replaceNode.SetIndex(tree.LEFTCHILDREN)
        parent.setLeftChildren(replaceNode)
    } else {
        replaceNode.SetIndex(tree.RIGHTCHILDREN)
        parent.setRightChildren(replaceNode)
    }
}

func (r *redBlackTreeNode) updateDepth() {
    r.SetDepth(int(math.Max(float64(r.getLeftChildren().Depth()), float64(r.getRightChildren().Depth()))) + 1)
}

func (r *redBlackTreeNode) findRoot() *redBlackTreeNode {
    if r.parent != nil {
        return r.parent.findRoot()
    }
    return r
}

func fixBalance(treeNode *redBlackTreeNode) {
    
    //一般情况:插入的父节点为黑色:
    //将插入的节点涂红
    parent := treeNode.getParent()
    if parent == nil {
        treeNode.SetFlag(_BLACK)
        return
    }
    treeNode.SetFlag(_RED)
    if parentFlag := parent.Flag(); parentFlag == _RED { //父节点是红色
        grandPa := parent.getParent()
        
        var uncle *redBlackTreeNode
        if parent.Index() == tree.LEFTCHILDREN {
            uncle = grandPa.getRightChildren()
        } else {
            uncle = grandPa.getLeftChildren()
        }
        if uncleFlag := uncle.Flag(); uncleFlag == _BLACK {
            //插入节点为红色 , 叔叔节点为黑色
            switch true {
            case parent.Index() == tree.LEFTCHILDREN && treeNode.Index() == tree.LEFTCHILDREN:
                rightRotate(grandPa)
                parent.SetFlag(_BLACK)
                grandPa.SetFlag(_RED)
            case parent.Index() == tree.LEFTCHILDREN && treeNode.Index() == tree.RIGHTCHILDREN:
                
                leftRotate(parent)
                rightRotate(grandPa)
                treeNode.SetFlag(_BLACK)
                grandPa.SetFlag(_RED)
            case parent.Index() == tree.RIGHTCHILDREN && treeNode.Index() == tree.RIGHTCHILDREN:
                
                leftRotate(grandPa)
                parent.SetFlag(_BLACK)
                grandPa.SetFlag(_RED)
            case parent.Index() == tree.RIGHTCHILDREN && treeNode.Index() == tree.LEFTCHILDREN:
                rightRotate(parent)
                leftRotate(grandPa)
                treeNode.SetFlag(_BLACK)
                grandPa.SetFlag(_RED)
            }
        } else { //插入节点父节点为红色 , 叔叔节点为红色
            switch true {
            case treeNode.Index() == tree.LEFTCHILDREN:
                grandPa.SetFlag(_RED)
                parent.SetFlag(_BLACK)
                uncle.SetFlag(_BLACK)
                fixBalance(grandPa)
            case treeNode.Index() == tree.RIGHTCHILDREN:
                grandPa.SetFlag(_RED)
                parent.SetFlag(_BLACK)
                uncle.SetFlag(_BLACK)
                fixBalance(grandPa)
            }
        }
    }
}

func NewRedBlackTreeNode(data interface{}) *redBlackTreeNode {
    node := &redBlackTreeNode{
        parent: nil,
        leftChildren: &redBlackTreeNode{
            flag: _BLACK,
        },
        rightChildren: &redBlackTreeNode{
            flag: _BLACK,
        },
        flag: _RED,
        data: data,
    }
    node.leftChildren.setParent(node)
    node.rightChildren.setParent(node)
    return node
}

func NewRedBlackTree() *RedBlackTree {
    return new(RedBlackTree)
}

func rightRotate(node *redBlackTreeNode) {
    parent, leftChildren := node.getParent(), node.getLeftChildren()
    //defer leftChildren.updateDepth()
    //defer node.updateDepth()
    
    sonRightChildren := leftChildren.getRightChildren()
    
    if parent != nil {
        if node.Index() == tree.RIGHTCHILDREN {
            parent.setRightChildren(leftChildren)
        } else {
            parent.setLeftChildren(leftChildren)
        }
    }
    
    leftChildren.SetIndex(node.Index())
    
    node.SetIndex(tree.RIGHTCHILDREN)
    leftChildren.setRightChildren(node)
    leftChildren.setParent(node.getParent())
    
    node.setParent(leftChildren)
    
    sonRightChildren.SetIndex(tree.LEFTCHILDREN)
    node.setLeftChildren(sonRightChildren)
    sonRightChildren.setParent(node)
}

func leftRotate(node *redBlackTreeNode) {
    
    parent, rightChildren := node.getParent(), node.getRightChildren()
    //defer rightChildren.updateDepth()
    //defer node.updateDepth()
    
    sonLeftChildren := rightChildren.getLeftChildren()
    
    if parent != nil {
        if node.Index() == tree.RIGHTCHILDREN {
            parent.setRightChildren(rightChildren)
        } else {
            parent.setLeftChildren(rightChildren)
        }
    }
    rightChildren.SetIndex(node.Index())
    
    node.SetIndex(tree.LEFTCHILDREN)
    rightChildren.setLeftChildren(node)
    rightChildren.setParent(node.getParent())
    
    node.setParent(rightChildren)
    
    sonLeftChildren.SetIndex(tree.RIGHTCHILDREN)
    node.setRightChildren(sonLeftChildren)
    sonLeftChildren.setParent(node)
    
}

//打印二叉树
func PrintTree(head *redBlackTreeNode, height int, to string, length int) {
    if head.data == nil {
        return
    }
    PrintTree(head.rightChildren, height+1, "right", length)
    
    val := to + "\"" + strconv.Itoa(head.data.(int)) + "\""
    if to == "right" {
        val = "⬇️" + val
    } else if to == "left" {
        val = "⬆️" + val
    }
    if head.Flag() == _BLACK {
        val = val + "black"
    } else {
        val = val + "red"
    }
    
    lenM := len([]rune(val))
    lenL := (length - lenM) / 2
    lenR := length - lenM - lenL
    val = GetSpace(lenL, length, head) + val + GetSpace(lenR, length, head)
    fmt.Println(GetSpace(height*length, length, head), val)
    PrintTree(head.leftChildren, height+1, "left", length)
}

//空格个数
func GetSpace(num, length int, node *redBlackTreeNode) string {
    space := " "
    var builder strings.Builder
    for i := 0; i < num; i++ {
        n := num/length - i/length
        ancestor := getAncestor(node, n)
        if i%length == 0 && ancestor.getParent() != nil {
            if ancestor.Index() == tree.RIGHTCHILDREN && node.data.(int) < ancestor.data.(int) {
                fmt.Fprintf(&builder, "|")
            } else if ancestor.Index() == tree.LEFTCHILDREN && node.data.(int) > ancestor.data.(int) {
                fmt.Fprintf(&builder, "|")
            } else {
                fmt.Fprintf(&builder, space)
            }
        } else {
            fmt.Fprintf(&builder, space)
        }
    }
    return builder.String()
}

func getAncestor(node *redBlackTreeNode, depth int) *redBlackTreeNode {
    if depth != 0 {
        depth--
        return getAncestor(node.getParent(), depth)
    } else {
        return node
    }
}

func (r *redBlackTreeNode) findMin() *redBlackTreeNode {
    if r.getLeftChildren().data != nil {
        return r.getLeftChildren().findMin()
    }
    return r
}

func (r *redBlackTreeNode) findMax() *redBlackTreeNode {
    if r.getRightChildren().data != nil {
        return r.getRightChildren().findMax()
    }
    return r
}

package tree

type Tree interface {
    GetRightSon() Tree
    SetRightSon(treeNode Tree) Tree
    GetLeftSon() Tree
    SetLeftSon(treeNode Tree) Tree
    GetParent() Tree
    SetParent(treeNode Tree) Tree
    GetData() interface{}
    SetData(data interface{}) Tree
    GetDepth() int
    SetDepth(depth int) Tree
    SetChildrenType(childrenIndex ChildrenIndex) Tree
    GetChildrenType() ChildrenIndex
    
    Insert(treeNode Tree) Tree
    Search(data interface{}) (Tree, error)
    Del(data interface{}) (Tree, error)
    FindMin() Tree
    FindMax() Tree
    
    Compare(tree Tree) CompareType
    
    Get(key interface{}) (interface{}, error)
    Set(key, value interface{}) Tree
}

type CompareType int8   //比较类型 用于比较 node 的差异(大于,小于,等于)
type ChildrenIndex int8 //节点位于父节点的位置
type DataMap map[interface{}]interface{}

const (
    EQUAL   CompareType = iota //节点等于当前节点
    GREATER                    //节点大于当前节点
    LESS                       //节点小于当前节点
    
)
const (
    
    ROOT        ChildrenIndex = iota //父亲节点
    LEFTCHILDREN                       //左孩子
    RIGHTCHILDREN                      //右孩子
)
package red_black_tree

import (
    "fmt"
    "math/rand"
    "testing"
)

func TestRedBlackTree_Insert(t *testing.T) {
    tree := NewRedBlackTree()
    for i := 1; i < 1000; i++ {
        fmt.Print(i, ",")
        tree = tree.Insert(NewRedBlackTreeNode(i))
    }
    fmt.Println()
    
    PrintTree(tree.root, 0, "root", 10)
    _, err := tree.Search(254)
    if err != nil {
        t.Log(err)
        t.Fail()
    }
}

func TestRedBlackTree_Delete(t *testing.T) {
    tree := NewRedBlackTree()
    for i := 1; i < 1000; i++ {
        fmt.Print(i, ",")
        tree = tree.Insert(NewRedBlackTreeNode(i))
    }
    fmt.Println()
    
    
    //if err := tree.Delete(12);err != nil {
    //    t.Log(err)
    //    t.Fail()
    //}
    //if err := tree.Delete(11);err != nil {
    //    t.Log(err)
    //    t.Fail()
    //}
    //if err := tree.Delete(9);err != nil {
    //    t.Log(err)
    //    t.Fail()
    //}
    if err := tree.Delete(5);err != nil {
       t.Log(err)
       t.Fail()
    }
    if err := tree.Delete(6);err != nil {
      t.Log(err)
      t.Fail()
    }
    if err := tree.Delete(2);err != nil {
      t.Log(err)
      t.Fail()
    }
    if err := tree.Delete(12);err != nil {
      t.Log(err)
      t.Fail()
    }
    
    PrintTree(tree.root, 0, "root", 10)
    _, err := tree.Search(11)
    if err == nil {
        t.Log(err)
        t.Fail()
    }
}

func BenchmarkRedBlackTree_Search(b *testing.B) {
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        tree := NewRedBlackTree()
        for i := 0; i < 1000; i++ {
            //fmt.Print(i, ",")
            tree = tree.Insert(NewRedBlackTreeNode(i))
        }
        for i := 0; i < 100000; i++ {
            _, err := tree.Search(rand.Intn(999))
            if err != nil {
                b.Log(err)
                b.Fail()
            }
        }
    }
}


好好学习,天天向上