C++ 数据结构学习 ---- 红黑树

目录

1. 头文件

1.1 红黑树头文件

2. 相关函数

2.1 插入函数

2.2 删除函数

2.3 更新高度

2.4 双黑调整

2.5 双红调整

3.完整代码

4.运行结果及截图

5. 逐步验证 


1. 头文件

1.1 红黑树头文件

注:需先引入C++ 数据结构学习 ---- 二叉搜索树_孤城寻欢的博客-CSDN博客的文件

#include "BST.h"


//外部节点也视作黑节点
#define IsBlack(p) ( ! (p) || ( RB_BLACK == (p)->color ) ) 
//非黑即红
#define IsRed(p) ( ! IsBlack(p) ) 
/*RedBlack高度更新条件*/
#define BlackHeightUpdated(x) (  \
   ( stature( (x).lc ) == stature( (x).rc ) ) && \
   ( (x).height == ( IsRed(& x) ? stature( (x).lc ) : stature( (x).lc ) + 1 ) ) )
/*来自父亲的引用*/
#define FromParentTo( x ) \
( IsRoot(x) ? BST<T>::_root : ( IsLChild(x) ? (x).parent->lc : (x).parent->rc ) )

template <typename T> class RedBlack : public BST<T> { //RedBlack树模板类
protected:
	void solveDoubleRed(BinNodePosi(T) x); //双红修正
	void solveDoubleBlack(BinNodePosi(T) x); //双黑修正
	int updateHeight(BinNodePosi(T) x); //更新节点x的高度(重写)
public:
	BinNodePosi(T) insert(const T& e); //插入(重写)
	bool remove(const T& e); //删除(重写)
 // BST::search()等其余接口可直接沿用
};

2. 相关函数

2.1 插入函数

//将e插入红黑树
template <typename T> BinNodePosi(T) RedBlack<T>::insert(const T& e) {
    if (!BST<T>::_root ){
        BinNodePosi(T) xOld=BST<T>::search(e); if (xOld) return xOld;
         BST<T>::_root = new BinNode<T>(e, BST<T>::_hot, NULL, NULL, 1); BST<T>::_size++;//根节点黑色
         return xOld;
    }
    if ( BST<T>::_size < 3) {
        BinNodePosi(T) xOld= BST<T>::search(e); if (xOld) return xOld;
        if( BST<T>::_size<2 )
         this->_root->lc = new BinNode<T>(e, BST<T>::_hot, NULL, NULL, 0);//第二层红色
        else  
          this->_root->rc = new BinNode<T>(e, BST<T>::_hot, NULL, NULL, 0); //第二层红色
        BST<T>::_size++;
        return  xOld;
    }
	BinNodePosi(T)& x = BST<T>::search(e); if (x) return x; //确认目标不存在(留意对BST<T>::_hot的设置)
	x = new BinNode<T>(e, BST<T>::_hot, NULL, NULL, 0); BST<T>::_size++; //创建红节点x:以BST<T>::_hot为父,黑高度0
	BinNodePosi(T) xOld = x; solveDoubleRed(x); return xOld; //经双红修正后,即可返回
} //无论e是否存在于原树中,返回时总有x->data == e

2.2 删除函数

 //从红黑树中删除关键码e
template <typename T> bool RedBlack<T>::remove(const T& e) { 
	BinNodePosi(T)& x = BST<T>::search(e); if (!x) return false; //确认目标存在(留意BST<T>::_hot的设置)
	BinNodePosi(T) r = removeAt(x, BST<T>::_hot); if (!(--BST<T>::_size)) return true; //实施删除
 // assert: BST<T>::_hot某一孩子刚被删除,且被r所指节点(可能是NULL)接替。以下检查是否失衡,并做必要调整
	if (!BST<T>::_hot) //若刚被删除的是根节点,则将其置黑,并更新黑高度
	{
		BST<T>::_root->color = RB_BLACK; updateHeight(BST<T>::_root); return true;
	}
	// assert: 以下,原x(现r)必非根,BST<T>::_hot必非空
	if (BlackHeightUpdated(*BST<T>::_hot)) return true; //若所有祖先的黑深度依然平衡,则无需调整
	if (IsRed(r)) //否则,若r为红,则只需令其转黑
	{
		r->color = RB_BLACK; r->height++; return true;
	}
	// assert: 以下,原x(现r)均为黑色
	   //*DSA*/printBinTree(BST<T>::_hot, 0, 0);
	solveDoubleBlack(r); return true; //经双黑调整后返回
} //若目标节点存在且被删除,返回true;否则返回false

2.3 更新高度

//更新节点高度
template <typename T> int RedBlack<T>::updateHeight(BinNodePosi(T) x) { 
	return x->height = IsBlack(x) + max(stature(x->lc), stature(x->rc)); //孩子黑高度通常相等,除非出现双黑
	// 红黑树中各节点左、右孩子的黑高度通常相等
	// 这里之所以取更大值,是便于在删除节点后的平衡调整过程中,正确更新被删除节点父亲的黑高度
	// 否则,rotateAt()会根据被删除节点的替代者(高度小一)设置父节点的黑高度
}

2.4 双黑调整

/******************************************************************************************
 * RedBlack双黑调整算法:解决节点x与被其替代的节点均为黑色的问题
 * 分为三大类共四种情况:
 *    BB-1 :2次颜色翻转,2次黑高度更新,1~2次旋转,不再递归
 *    BB-2R:2次颜色翻转,2次黑高度更新,0次旋转,不再递归
 *    BB-2B:1次颜色翻转,1次黑高度更新,0次旋转,需要递归
 *    BB-3 :2次颜色翻转,2次黑高度更新,1次旋转,转为BB-1或BB2R
 ******************************************************************************************/
template <typename T> void RedBlack<T>::solveDoubleBlack(BinNodePosi(T) r) {
    BinNodePosi(T) p = r ? r->parent : BST<T>::_hot; if (!p) return; //r的父亲
    BinNodePosi(T) s = (r == p->lc) ? p->rc : p->lc; //r的兄弟
    if (IsBlack(s)) { //兄弟s为黑
        BinNodePosi(T) t = NULL; //s的红孩子(若左、右孩子皆红,左者优先;皆黑时为NULL)
        if (IsRed(s->rc)) t = s->rc; //右子
        if (IsRed(s->lc)) t = s->lc; //左子
        if (t) { //黑s有红孩子:BB-1
           //*DSA*/printf("  case BB-1: Child ("); print(s->lc); printf(") of BLACK sibling ("); print(s); printf(") is RED\n");
            RBColor oldColor = p->color; //备份原子树根节点p颜色,并对t及其父亲、祖父
         // 以下,通过旋转重平衡,并将新子树的左、右孩子染黑
            BinNodePosi(T) b = FromParentTo(*p) = BST<T>::rotateAt(t); //旋转
            if (HasLChild(*b)) { b->lc->color = RB_BLACK; updateHeight(b->lc); } //左子
            if (HasRChild(*b)) { b->rc->color = RB_BLACK; updateHeight(b->rc); } //右子
            b->color = oldColor; updateHeight(b); //新子树根节点继承原根节点的颜色
            //*DSA*/printBinTree(b, 0, 0);
        }
        else { //黑s无红孩子
            s->color = RB_RED; s->height--; //s转红
            if (IsRed(p)) { //BB-2R
               //*DSA*/printf("  case BB-2R: Both children ("); print(s->lc); printf(") and ("); print(s->rc); printf(") of BLACK sibling ("); print(s); printf(") are BLACK, and parent ("); print(p); printf(") is RED\n"); //s孩子均黑,p红
                p->color = RB_BLACK; //p转黑,但黑高度不变
                //*DSA*/printBinTree(p, 0, 0);
            }
            else { //BB-2B
            //*DSA*/printf("  case BB-2R: Both children ("); print(s->lc); printf(") and ("); print(s->rc); printf(") of BLACK sibling ("); print(s); printf(") are BLACK, and parent ("); print(p); printf(") is BLACK\n"); //s孩子均黑,p黑
                p->height--; //p保持黑,但黑高度下降
                //*DSA*/printBinTree(p, 0, 0);
                solveDoubleBlack(p); //递归上溯
            }
        }
    }
    else { //兄弟s为红:BB-3
    //*DSA*/printf("  case BB-3: sibling ("); print(s); printf(" is RED\n"); //s红(双子俱黑)
        s->color = RB_BLACK; p->color = RB_RED; //s转黑,p转红
        BinNodePosi(T) t = IsLChild(*s) ? s->lc : s->rc; //取t与其父s同侧
        BST<T>::_hot = p; FromParentTo(*p) = BST<T>::rotateAt(t); //对t及其父亲、祖父做平衡调整
        //*DSA*/printBinTree<T>(s, 0, 0);
        solveDoubleBlack(r); //继续修正r处双黑——此时的p已转红,故后续只能是BB-1或BB-2R
    }
}

2.5 双红调整

/******************************************************************************************
 * RedBlack双红调整算法:解决节点x与其父均为红色的问题。分为两大类情况:
 *    RR-1:2次颜色翻转,2次黑高度更新,1~2次旋转,不再递归
 *    RR-2:3次颜色翻转,3次黑高度更新,0次旋转,需要递归
 ******************************************************************************************/
template <typename T> void RedBlack<T>::solveDoubleRed(BinNodePosi(T) x) { //x当前必为红
    if (IsRoot(*x)) //若已(递归)转至树根,则将其转黑,整树黑高度也随之递增
    {
        BST<T>::_root->color = RB_BLACK; BST<T>::_root->height++; return;
    } //否则,x的父亲p必存在
    BinNodePosi(T) p = x->parent; if (IsBlack(p)) return; //若p为黑,则可终止调整。否则
    BinNodePosi(T) g = p->parent; //既然p为红,则x的祖父必存在,且必为黑色
    BinNodePosi(T) u = uncle(x); //以下,视x叔父u的颜色分别处理
    if (IsBlack(u)) { //u为黑色(含NULL)时 //*DSA*/printf("  case RR-1:\n");
        if (IsLChild(*x) == IsLChild(*p)) //若x与p同侧(即zIg-zIg或zAg-zAg),则
            p->color = RB_BLACK; //p由红转黑,x保持红
        else //若x与p异侧(即zIg-zAg或zAg-zIg),则
            x->color = RB_BLACK; //x由红转黑,p保持红
        g->color = RB_RED; //g必定由黑转红
  / 以上虽保证总共两次染色,但因增加了判断而得不偿失
  / 在旋转后将根置黑、孩子置红,虽需三次染色但效率更高
        BinNodePosi(T) gg = g->parent; //曾祖父(great-grand parent)
        BinNodePosi(T) r = FromParentTo(*g) = BST<T>::rotateAt(x); //调整后的子树根节点
        r->parent = gg; //与原曾祖父联接
    }
    else { //若u为红色 //*DSA*/printf("  case RR-2:\n");
        p->color = RB_BLACK; p->height++; //p由红转黑
        u->color = RB_BLACK; u->height++; //u由红转黑
        g->color = RB_RED; //在B-树中g相当于上交给父节点的关键码,故暂标记为红
        solveDoubleRed(g); //继续调整:若已至树根,接下来的递归会将g转黑(尾递归,不难改为迭代)
    }
}

3.完整代码

#include "BST.h"


//外部节点也视作黑节点
#define IsBlack(p) ( ! (p) || ( RB_BLACK == (p)->color ) ) 
//非黑即红
#define IsRed(p) ( ! IsBlack(p) ) 
/*RedBlack高度更新条件*/
#define BlackHeightUpdated(x) (  \
   ( stature( (x).lc ) == stature( (x).rc ) ) && \
   ( (x).height == ( IsRed(& x) ? stature( (x).lc ) : stature( (x).lc ) + 1 ) ) )
/*来自父亲的引用*/
#define FromParentTo( x ) \
( IsRoot(x) ? BST<T>::_root : ( IsLChild(x) ? (x).parent->lc : (x).parent->rc ) )

template <typename T> class RedBlack : public BST<T> { //RedBlack树模板类
protected:
	void solveDoubleRed(BinNodePosi(T) x); //双红修正
	void solveDoubleBlack(BinNodePosi(T) x); //双黑修正
	int updateHeight(BinNodePosi(T) x); //更新节点x的高度(重写)
public:
	BinNodePosi(T) insert(const T& e); //插入(重写)
	bool remove(const T& e); //删除(重写)
 // BST::search()等其余接口可直接沿用
};


//将e插入红黑树
template <typename T> BinNodePosi(T) RedBlack<T>::insert(const T& e) {
    if (!BST<T>::_root ){
        BinNodePosi(T) xOld=BST<T>::search(e); if (xOld) return xOld;
         BST<T>::_root = new BinNode<T>(e, BST<T>::_hot, NULL, NULL, 1); BST<T>::_size++;//根节点黑色
         return xOld;
    }
    if ( BST<T>::_size < 3) {
        BinNodePosi(T) xOld= BST<T>::search(e); if (xOld) return xOld;
        if( BST<T>::_size<2 )
         this->_root->lc = new BinNode<T>(e, BST<T>::_hot, NULL, NULL, 0);//第二层红色
        else  
          this->_root->rc = new BinNode<T>(e, BST<T>::_hot, NULL, NULL, 0); //第二层红色
        BST<T>::_size++;
        return  xOld;
    }
	BinNodePosi(T)& x = BST<T>::search(e); if (x) return x; //确认目标不存在(留意对BST<T>::_hot的设置)
	x = new BinNode<T>(e, BST<T>::_hot, NULL, NULL, 0); BST<T>::_size++; //创建红节点x:以BST<T>::_hot为父,黑高度0
	BinNodePosi(T) xOld = x; solveDoubleRed(x); return xOld; //经双红修正后,即可返回
} //无论e是否存在于原树中,返回时总有x->data == e

  
 //从红黑树中删除关键码e
template <typename T> bool RedBlack<T>::remove(const T& e) { 
	BinNodePosi(T)& x = BST<T>::search(e); if (!x) return false; //确认目标存在(留意BST<T>::_hot的设置)
	BinNodePosi(T) r = removeAt(x, BST<T>::_hot); if (!(--BST<T>::_size)) return true; //实施删除
 // assert: BST<T>::_hot某一孩子刚被删除,且被r所指节点(可能是NULL)接替。以下检查是否失衡,并做必要调整
	if (!BST<T>::_hot) //若刚被删除的是根节点,则将其置黑,并更新黑高度
	{
		BST<T>::_root->color = RB_BLACK; updateHeight(BST<T>::_root); return true;
	}
	// assert: 以下,原x(现r)必非根,BST<T>::_hot必非空
	if (BlackHeightUpdated(*BST<T>::_hot)) return true; //若所有祖先的黑深度依然平衡,则无需调整
	if (IsRed(r)) //否则,若r为红,则只需令其转黑
	{
		r->color = RB_BLACK; r->height++; return true;
	}
	// assert: 以下,原x(现r)均为黑色
	   //*DSA*/printBinTree(BST<T>::_hot, 0, 0);
	solveDoubleBlack(r); return true; //经双黑调整后返回
} //若目标节点存在且被删除,返回true;否则返回false
//更新节点高度
template <typename T> int RedBlack<T>::updateHeight(BinNodePosi(T) x) { 
	return x->height = IsBlack(x) + max(stature(x->lc), stature(x->rc)); //孩子黑高度通常相等,除非出现双黑
	/*DSA*/// 红黑树中各节点左、右孩子的黑高度通常相等
	/*DSA*/// 这里之所以取更大值,是便于在删除节点后的平衡调整过程中,正确更新被删除节点父亲的黑高度
	/*DSA*/// 否则,rotateAt()会根据被删除节点的替代者(高度小一)设置父节点的黑高度
}

/******************************************************************************************
 * RedBlack双黑调整算法:解决节点x与被其替代的节点均为黑色的问题
 * 分为三大类共四种情况:
 *    BB-1 :2次颜色翻转,2次黑高度更新,1~2次旋转,不再递归
 *    BB-2R:2次颜色翻转,2次黑高度更新,0次旋转,不再递归
 *    BB-2B:1次颜色翻转,1次黑高度更新,0次旋转,需要递归
 *    BB-3 :2次颜色翻转,2次黑高度更新,1次旋转,转为BB-1或BB2R
 ******************************************************************************************/
template <typename T> void RedBlack<T>::solveDoubleBlack(BinNodePosi(T) r) {
    BinNodePosi(T) p = r ? r->parent : BST<T>::_hot; if (!p) return; //r的父亲
    BinNodePosi(T) s = (r == p->lc) ? p->rc : p->lc; //r的兄弟
    if (IsBlack(s)) { //兄弟s为黑
        BinNodePosi(T) t = NULL; //s的红孩子(若左、右孩子皆红,左者优先;皆黑时为NULL)
        if (IsRed(s->rc)) t = s->rc; //右子
        if (IsRed(s->lc)) t = s->lc; //左子
        if (t) { //黑s有红孩子:BB-1
           //*DSA*/printf("  case BB-1: Child ("); print(s->lc); printf(") of BLACK sibling ("); print(s); printf(") is RED\n");
            RBColor oldColor = p->color; //备份原子树根节点p颜色,并对t及其父亲、祖父
         // 以下,通过旋转重平衡,并将新子树的左、右孩子染黑
            BinNodePosi(T) b = FromParentTo(*p) = BST<T>::rotateAt(t); //旋转
            if (HasLChild(*b)) { b->lc->color = RB_BLACK; updateHeight(b->lc); } //左子
            if (HasRChild(*b)) { b->rc->color = RB_BLACK; updateHeight(b->rc); } //右子
            b->color = oldColor; updateHeight(b); //新子树根节点继承原根节点的颜色
            //*DSA*/printBinTree(b, 0, 0);
        }
        else { //黑s无红孩子
            s->color = RB_RED; s->height--; //s转红
            if (IsRed(p)) { //BB-2R
               //*DSA*/printf("  case BB-2R: Both children ("); print(s->lc); printf(") and ("); print(s->rc); printf(") of BLACK sibling ("); print(s); printf(") are BLACK, and parent ("); print(p); printf(") is RED\n"); //s孩子均黑,p红
                p->color = RB_BLACK; //p转黑,但黑高度不变
                //*DSA*/printBinTree(p, 0, 0);
            }
            else { //BB-2B
            //*DSA*/printf("  case BB-2R: Both children ("); print(s->lc); printf(") and ("); print(s->rc); printf(") of BLACK sibling ("); print(s); printf(") are BLACK, and parent ("); print(p); printf(") is BLACK\n"); //s孩子均黑,p黑
                p->height--; //p保持黑,但黑高度下降
                //*DSA*/printBinTree(p, 0, 0);
                solveDoubleBlack(p); //递归上溯
            }
        }
    }
    else { //兄弟s为红:BB-3
    //*DSA*/printf("  case BB-3: sibling ("); print(s); printf(" is RED\n"); //s红(双子俱黑)
        s->color = RB_BLACK; p->color = RB_RED; //s转黑,p转红
        BinNodePosi(T) t = IsLChild(*s) ? s->lc : s->rc; //取t与其父s同侧
        BST<T>::_hot = p; FromParentTo(*p) = BST<T>::rotateAt(t); //对t及其父亲、祖父做平衡调整
        //*DSA*/printBinTree<T>(s, 0, 0);
        solveDoubleBlack(r); //继续修正r处双黑——此时的p已转红,故后续只能是BB-1或BB-2R
    }
}

/******************************************************************************************
 * RedBlack双红调整算法:解决节点x与其父均为红色的问题。分为两大类情况:
 *    RR-1:2次颜色翻转,2次黑高度更新,1~2次旋转,不再递归
 *    RR-2:3次颜色翻转,3次黑高度更新,0次旋转,需要递归
 ******************************************************************************************/
template <typename T> void RedBlack<T>::solveDoubleRed(BinNodePosi(T) x) { //x当前必为红
    if (IsRoot(*x)) //若已(递归)转至树根,则将其转黑,整树黑高度也随之递增
    {
        BST<T>::_root->color = RB_BLACK; BST<T>::_root->height++; return;
    } //否则,x的父亲p必存在
    BinNodePosi(T) p = x->parent; if (IsBlack(p)) return; //若p为黑,则可终止调整。否则
    BinNodePosi(T) g = p->parent; //既然p为红,则x的祖父必存在,且必为黑色
    BinNodePosi(T) u = uncle(x); //以下,视x叔父u的颜色分别处理
    if (IsBlack(u)) { //u为黑色(含NULL)时 //*DSA*/printf("  case RR-1:\n");
        if (IsLChild(*x) == IsLChild(*p)) //若x与p同侧(即zIg-zIg或zAg-zAg),则
            p->color = RB_BLACK; //p由红转黑,x保持红
        else //若x与p异侧(即zIg-zAg或zAg-zIg),则
            x->color = RB_BLACK; //x由红转黑,p保持红
        g->color = RB_RED; //g必定由黑转红
  / 以上虽保证总共两次染色,但因增加了判断而得不偿失
  / 在旋转后将根置黑、孩子置红,虽需三次染色但效率更高
        BinNodePosi(T) gg = g->parent; //曾祖父(great-grand parent)
        BinNodePosi(T) r = FromParentTo(*g) = BST<T>::rotateAt(x); //调整后的子树根节点
        r->parent = gg; //与原曾祖父联接
    }
    else { //若u为红色 //*DSA*/printf("  case RR-2:\n");
        p->color = RB_BLACK; p->height++; //p由红转黑
        u->color = RB_BLACK; u->height++; //u由红转黑
        g->color = RB_RED; //在B-树中g相当于上交给父节点的关键码,故暂标记为红
        solveDoubleRed(g); //继续调整:若已至树根,接下来的递归会将g转黑(尾递归,不难改为迭代)
    }
}

#include<iostream>
using namespace std;

string redblack(int n) {
	if (n==1) return "黑";
	else return "红";
}

int main() {
	RedBlack<int> rb;
	BinNodePosi(int) root = rb.insertAsRoot(3);
	rb.insert(1);
	rb.insert(9);
	rb.travLevel(root);
	rb.insert(2);
	cout << redblack(rb.search(2)->color)<<endl;
	rb.travLevel(root);
	rb.insert(0);
	cout << redblack(rb.search(0)->color) << endl;
	rb.travLevel(root);
	rb.insert(11);
	cout << redblack(rb.search(11)->color) << endl;
	rb.travLevel(root);
	rb.insert(7);
	cout << redblack(rb.search(7)->color) << endl;
	rb.travLevel(root);
	rb.insert(19);
	cout << redblack(rb.search(11)->color) << endl;
	rb.travLevel(root);
	rb.insert(4);
	rb.travLevel(root);
	rb.insert(15);
	rb.travLevel(root);
	rb.insert(18);
	rb.travLevel(root);
	rb.insert(5);
	rb.travLevel(root);
	rb.insert(14);
	rb.travLevel(root);
	rb.insert(13);
	rb.travLevel(root);
	rb.insert(10);
	rb.travLevel(root);
	rb.insert(16);
	rb.travLevel(root);
	rb.insert(16);
	rb.travLevel(root);
	rb.insert(3);
	rb.travLevel(root);
	rb.insert(8);
	rb.travLevel(root);
	rb.insert(17);	
	rb.travIn(root);//0 1 2 3 4 5 7 8 10 11 12 9 13 14 15 16 17 18 19
	rb.travLevel(root);
	rb.remove(4);
	rb.travIn(root);//0 1 2 3 5 7 8 10 11 12 9 13 14 15 16 17 18 19		
	rb.travLevel(root);//9 3 15 1 7 13 18 0 2 5 8 11 14 16 19 10 17
	//验证结果
	cout << redblack( rb.search(9)->color);
	cout << redblack( rb.search(3)->color);
	cout << redblack( rb.search(15)->color);
	cout << redblack( rb.search(1)->color);
	cout << redblack( rb.search(7)->color);
	cout << redblack( rb.search(13)->color);
	cout << redblack( rb.search(18)->color);
	cout << redblack( rb.search(0)->color);
	cout << redblack(rb.search(2)->color);
	cout << redblack(rb.search(5)->color);
	cout << redblack(rb.search(8)->color);
	cout << redblack(rb.search(11)->color);
	cout << redblack(rb.search(14)->color);
	cout << redblack(rb.search(16)->color);
	cout << redblack(rb.search(19)->color);
	cout << redblack(rb.search(10)->color);
	cout << redblack(rb.search(17)->color);
	cout << endl;
	system("pause");
	return 0;
}

4.运行结果及截图

5. 逐步验证 

首先插入3 1 9

在插入2后,判断此时2的颜色为红色,无误!

  

 在插入0后,判断此时0的颜色为红色,无误!

  在插入11后,判断此时11的颜色为红色,无误!

 在插入7后,判断此时7的颜色为红色,无误!

 在插入19后,判断此时11的颜色为黑色,无误!

 随后依次插入4、15、18、5、14、13、10、16、3、8、17

因为这个版本的红黑树不支持相同的值在书中,所以重复的值被无视了!

最后删除 4
   层次遍历的结果为  黑  黑黑  黑红红红  红红黑黑黑黑黑黑   红红
 显然结果正确,其实红黑树其实是B树的变种,明白B树之后,红黑树将红孩子提升一层至父节点同级,看成一棵B树,而红与黑的失衡其实就是一棵B树的上溢与下溢,而红与黑的修复其实就是B树的上溢与下溢解决方法!

以上相关代码参考邓俊辉老师的《c++语言版数据结构》!

猜你喜欢

转载自blog.csdn.net/qq_58240448/article/details/127886838