【数据结构】基础:红黑树

【数据结构】基础:红黑树(含c++源码)

摘要:本文主要介绍红黑树的概念与基本实现。首先对于红黑树的概念和性质进行说明,再根据红黑树的特性设定相应的实现方案。再实现过程中,主要介绍了红黑树的插入步骤,首先补充了关于树的旋转知识,介绍了如何控制树的高度与平衡,再通过搜索的性质与红黑树的性质入手,完成红黑树的插入,实现后对其进行验证。最后将其与AVL树进行了性能比较,展示红黑树的优点。


文章目录

  • 【数据结构】基础:红黑树(含c++源码)
    • 一、概述
    • 二、红黑树的实现
    • 三、红黑树的插入
      • 3.0 补充:旋转控制
        • 2.3.1 右单旋(RotateR)
        • 2.3.2 左单旋(RotateL)
      • 3.1 搜索插入
      • 3.2 颜色与平衡控制
        • 3.2.1 情况一:父亲节点不为红色
        • 3.2.2 情况二:父亲节点不为红色且叔叔节点存在且为红
        • 3.2.3 情况三:父亲节点不为红色且叔叔节点不存在或存在且为黑
      • 3.3 插入过程示例
        • 3.3.1 以升序插入构建红黑树
        • 3.3.2 以降序插入构建红黑树
        • 3.3.3 随机插入构建红黑树
    • 四、红黑树的验证
      • 4.1 搜索树验证
      • 4.2 红黑树验证
      • 4.3 完整代码
    • 五、性能比较
    • 六、完整代码

一、概述

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的

红黑树遵循以下性质:

  1. 每个结点不是红色就是黑色
  2. 根节点是黑色的
  3. 如果一个节点是红色的,则它的两个孩子结点是黑色的,即没有连续的红节点
  4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点
  5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

根据以上性质,可以保证最长路径不超过最短路径的两倍,原因为:

  • 由性质4,当根到任一个叶节点的简单路径最短时,这条路径必须全是由黑结点构成
  • 由性质3,当某条路径最长时,这条路径必须由黑红相间的路径构成,此时红节点路径和黑节点相同

示例用图如下:

【数据结构】基础:红黑树_第1张图片

二、红黑树的实现

红黑树的形式采取与AVL树相似的方案三叉链,由于在红黑树在插入节点时,需要更新祖先的节点颜色,因此设置了_parent指针方便更新。对于节点的结构,增加了枚举类型Colour来记录颜色。关于节点的构造函数将节点的初始颜色设置为红色,便于后续插入过程。否则违反了性质4,增加插入难度。

对于树的结构,设置根节点即可,通过根节点来访问整课树形结构,具体代码如下:

enum Colour{
	RED,
	BLACK
};

template<class K, class K>
class RBTreeNode {
public:
	RBTreeNode<K, V>* _left;
	RBTreeNode<K, V>* _right;
	RBTreeNode<K, V>* _parent;

	pair<K, V> _KeyValue;

	Colour _colour;

	RBTreeNode(const pair<K, V>& KeyValue)
		:_left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _colour(RED)
		, _KeyValue(KeyValue)
	{}
};

template<class K,class V>
class RBTree {
	typedef RBTreeNode<K, V> RBTreeNode;
private:
	RBTreeNode* _root;
public:
	RBTree()
		:_root(nullptr);
	{}
};

三、红黑树的插入

红黑树的插入是在搜索二叉树的条件下进行改进,先进行搜索,再进行颜色与平衡控制,从而达到降低高度的目的。因此主要基本思想可以分为:

  • 根据二叉搜索树的规则寻找插入位置
  • 调节颜色与平衡,使其符合红黑树的性质与降低树的高度

3.0 补充:旋转控制

2.3.1 右单旋(RotateR)

几何特征:当新节点插入较高左子树的左侧时,将其需要将其像右旋转,图示如下:

【数据结构】基础:红黑树_第2张图片

旋转意义:将高度较高的子树的最大节点上提为根,将原来的根下移为子树的根,使得高度平衡。如此原来高度为H+2的子树降低为H+1,原来H的子树提高为H+1。

实现过程

  • 从总体上观察,是将cur的右子树作为了parent的左子树,再将cur的右子树指向parent

    void RotateR(AVLTreeNode* parent) {
        AVLTreeNode* cur = parent->_left;
        AVLTreeNode* curR = cur->_right;
    
        parent->_left = curR;
        curR->_parent = parent;
    
        cur->_right = parent;
        parent->_parent = cur;
    }
    
  • 对于整棵树的整体已经变化完毕了,但是还需要对树外的指针进行操作,即对于parentparent也要进行连接。如果parent是根节点就不需要连接,将cur作为根,否则就需要找出链接的子树,并完成相互链接。

    void RotateR(AVLTreeNode* parent) {
        // cur一定存在 无需判断空
        AVLTreeNode* cur = parent->_left;
        AVLTreeNode* curR = cur->_right;
        // 对于parent的parent也要进行连接
        AVLTreeNode* parentParent = parent->_parent;
    
        parent->_left = curR;
    	curR->_parent = parent;
    
        cur->_right = parent;
        parent->_parent = cur;
    	// 如果parent是根节点就不需要连接,将cur作为根
        if (parent == _root) {
            _root = cur;
            _root->_parent == nullptr;
        }
        // 将cur作为根,否则就需要找出链接的子树,并完成相互链接
        else{
            if (parentParent->_left == parent) {
                parentParent->_left = cur;
                cur->_parent = parentParent;
            }
            else {
                parentParent->_right = cur;
                cur->_parent = parentParent;
            }
        }
    }
    
  • 由于存在空指针的情况,因此需要对节点的子树进行判断

    void RotateR(AVLTreeNode* parent) {
        AVLTreeNode* cur = parent->_left;
        AVLTreeNode* curR = cur->_right;
        // 对于parent的parent也要进行连接
        AVLTreeNode* parentParent = parent->_parent;
    
        parent->_left = curR;
        // curR可能为空,因此需要对其进行空指针的判断
        if (curR != nullptr) {
            curR->_parent = parent;
        }
        cur->_right = parent;
        parent->_parent = cur;
    	// 如果parent是根节点就不需要连接,将cur作为根
        if (parent == _root) {
            _root = cur;
            _root->_parent == nullptr;
        }
        // 将cur作为根,否则就需要找出链接的子树,并完成相互链接
        else{
            if (parentParent->_left == parent) {
                parentParent->_left = cur;
                cur->_parent = parentParent;
            }
            else {
                parentParent->_right = cur;
                cur->_parent = parentParent;
            }
        }
    }
    
  • 最后对平衡因子进行相应的修改

    cur->_balanceFactor = parent->_balanceFactor = 0;
    
  • 完整代码

    void RotateR(AVLTreeNode* parent) {
        AVLTreeNode* cur = parent->_left;
        AVLTreeNode* curR = cur->_right;
        // 对于parent的parent也要进行连接
        AVLTreeNode* parentParent = parent->_parent;
    
        parent->_left = curR;
        // curR可能为空,因此需要对其进行空指针的判断
        if (curR != nullptr) {
            curR->_parent = parent;
        }
        cur->_right = parent;
        parent->_parent = cur;
    	// 如果parent是根节点就不需要连接,将cur作为根
        if (parent == _root) {
            _root = cur;
            _root->_parent == nullptr;
        }
        // 将cur作为根,否则就需要找出链接的子树,并完成相互链接
        else{
            if (parentParent->_left == parent) {
                parentParent->_left = cur;
                cur->_parent = parentParent;
            }
            else {
                parentParent->_right = cur;
                cur->_parent = parentParent;
            }
        }
        cur->_balanceFactor = parent->_balanceFactor = 0;
    }
    

2.3.2 左单旋(RotateL)

几何特征:当新节点插入较高右子树的右侧时,将其需要将其像左旋转,图示如下:

【数据结构】基础:红黑树_第3张图片

旋转意义:将高度较高的子树的最大节点上提为根,将原来的根下移为子树的根,使得高度平衡。如此原来高度为H+2的子树降低为H+1,原来H的子树提高为H+1。

实现过程:与右单旋类似,只是方向不同,在此不做过多赘述

void RotateL(AVLTreeNode* parent) {
    AVLTreeNode* cur = parent->_right;
    AVLTreeNode* curL = cur->_left;

    AVLTreeNode* parentParent = parent->_parent;

    parent->_right = curL;
    if (curL != nullptr) {
        curR->_parent = parent;
    }

    parent->_parent = cur;
    cur->_left = parent;

    if (parent == _root) {
        _root = cur;
        _root->_parent = nullptr;
    }
    else {
        if (parentParent->_left == parent) {
            parentParent->_left = cur;
            cur->_parent = parentParent;
        }
        else {
            parentParent->_right = cur;
            cur->_parent = parentParent;
        }
    }
}

3.1 搜索插入

该步的方法与搜索二叉树的插入过程相似,首先找出键值对的键找出插入位置,其中记录parentcur指针,便于在找到后简单的找出与父节点连接的方向以及完成插入节点的parent指针的连接。

bool Insert(const pair<K, V>& keyValue) {
    if (_root == nullptr) {
        _root = new RBTreeNode(keyValue);
        _root->_colour = BLACK;
        return true;
    }

    RBTreeNode* parent = nullptr;
    RBTreeNode* cur = _root;
    while (cur) {
        if (cur->_KeyValue.first < keyValue.first) {
            parent = cur;
            cur = cur->_right;
        }
        else if (cur->_KeyValue.first > keyValue.first) {
            parent = cur;
            cur = cur->_left;
        }
        else {
            return false;
        }
    }

    cur = new RBTreeNode(keyValue);
    cur->_colour = RED;
    if (parent->_KeyValue.first < keyValue.first) {
        parent->_right = cur;
        cur->_parent = parent;
    }
    else {
        parent->_left = cur;
        cur->_parent = parent;
    }
    // 控制平衡
}

3.2 颜色与平衡控制

对于插入的节点,默认设置为红色。如果设置为黑色可能会对黑色节点的数目造成影响,由于要符合性质4,在修改颜色时会造成麻烦。 默认为红色后,对于颜色与平衡的控制可以分为两大类

3.2.1 情况一:父亲节点不为红色

直接出入即可,说插入节点为红色节点,不存在破坏红黑树结构的可能,但需要时刻保持根节点为黑色

// 控制平衡
_root->_colour = BLACK;

3.2.2 情况二:父亲节点不为红色且叔叔节点存在且为红

几何特征:在未插入节点时,父亲为红色,且叔叔也为红色,当插入节点后会出现两种连续的红色,不符合红黑树插入的性质

几何图示

【数据结构】基础:红黑树_第4张图片

颜色修改

  • 将父节点与叔叔节点修改为黑色,并将爷爷节点修改为红色
  • 由于爷爷进行了颜色修改,可能出现两个连续的红节点,因此是一个父亲节点迭代的过程
  • 对于根节点的黑色保持

修改意义:保持黑色节点在不同路径下的数量一致

平衡修改:树认为平衡状态不需要修改

实现过程

  • 判定父亲节点与叔叔节点的颜色与方向
  • 进行颜色修改
  • 迭代祖先颜色修改过程
  • 对于根节点的颜色保持

具体代码

while (parent && parent->_colour == RED){
    RBTreeNode* grathfather = parent->_parent;
    if (grathfather->_left == parent) {
        RBTreeNode* uncle = grathfather->_right;
        // 情况一:父亲节点不为红色且叔叔节点存在且为红
        if (uncle && uncle.colour == RED) {
            parent->_colour = uncle->_colour = BLACK;
            grathfather->_colour = RED;
            // 迭代
            cur = grathfather;
            parent = cur->_parent;
        }
        else {

        }
    }
    else {
        RBTreeNode* uncle = grathfather->_left;
        // 情况一:父亲节点不为红色且叔叔节点存在且为红
        if (uncle && uncle.colour == RED) {
            parent->_colour = uncle->_colour = BLACK;
            grathfather->_colour = RED;
            // 迭代
            cur = grathfather;
            parent = cur->_parent;
        }
        else {

        }
    }
}

3.2.3 情况三:父亲节点不为红色且叔叔节点不存在或存在且为黑

几何特征:在未插入节点时,父亲为红色,且叔叔为黑色,当插入节点后会出现两种连续的红色,不符合红黑树插入的性质。而且当叔叔为黑时或不存在时,当新节点插入,将会使得性质4被破坏,此时的树也并非符合条件的接近平衡。为此需要进行旋转操作。

几何图示

【数据结构】基础:红黑树_第5张图片

平衡修改

  • 当新插入节点与树较高位同侧,采用单旋即可

  • 当新插入节点与树较高位异侧,采用双旋即可

【数据结构】基础:红黑树_第6张图片

颜色修改:在旋转后,保持黑色节点的数量一致,其中新子树的根为黑色,子节点均为红色

实现过程

  • 判定父亲节点与叔叔节点的颜色与方向,确定插入的方向与高度更高的方向的关系,完成平衡修改方案判断
  • 颜色修改
  • 结束迭代

具体代码

while (parent && parent->_colour == RED){
    RBTreeNode* grathfather = parent->_parent;
    if (grathfather->_left == parent) {
        RBTreeNode* uncle = grathfather->_right;
        //父亲节点不为红色且叔叔节点存在且为红
        if (uncle && uncle.colour == RED) {
            parent->_colour = uncle->_colour = BLACK;
            grathfather->_colour = RED;
            // 迭代
            cur = grathfather;
            parent = cur->_parent;
        }
        //父亲节点不为红色且叔叔节点不存在或存在且为黑
        else {
            // 左左:右单旋
            //		grathfather
            //	  parent
            //  cur
            if (cur == parent->_left) {
                RotateR(grathfather);
                parent->_colour = BLACK;
                grathfather->_colour = RED;
            }
            // 左右:左单旋 -- 右单旋
            //        grathfather
            //     parent
            //        cur
            else {
                RotateL(parent);
                RotateR(grathfather);
                cur->_colour = BLACK;
                grathfather->_colour = RED;
            }
            break;
        }
    }
    else {
        RBTreeNode* uncle = grathfather->_left;
        // 情况一:父亲节点不为红色且叔叔节点存在且为红
        if (uncle && uncle.colour == RED) {
            parent->_colour = uncle->_colour = BLACK;
            grathfather->_colour = RED;
            // 迭代
            cur = grathfather;
            parent = cur->_parent;
        }
        else {
            // 右右:左单旋
            //		grathfather
            //			parent
            //				cur
            if (cur == parent->_right) {
                RotateL(grathfather);
                parent->_colour = BLACK;
                grathfather->_colour = RED;
            }
            else {
                // 右左:右单旋 -- 左单旋
                //		grathfather
                //			parent
                //		cur
                RotateR(parent);
                RotateL(grathfather);
                cur->_colour = BLACK;
                grathfather->_colour = RED;
            }
            break;
        }
    }
}

3.3 插入过程示例

3.3.1 以升序插入构建红黑树

3.3.2 以降序插入构建红黑树

3.3.3 随机插入构建红黑树

四、红黑树的验证

红黑树的检测分为两步:

  • 检测其是否满足二叉搜索树
  • 检测其是否满足红黑树的性质

4.1 搜索树验证

通过中序遍历来完成对二叉搜索树的检查

public:
	void InOrder(){
		_InOrder(_root);
	}
private:
	void _InOrder(RBTreeNode* root){
		if (root == NULL)
			return;
		_InOrder(root->_left);
		cout << root->_KeyValue.first << ":" << root->_KeyValue.second << endl;
		_InOrder(root->_right);
	}

4.2 红黑树验证

主要步骤为:

  • 验证根节点的颜色为黑色

    if (_root && _root->_colour == RED){
        cout << "根节点不是黑色" << endl;
        return false;
    }
    
  • 验证没有连续的红节点

    if (root->_colour == RED && root->_parent->_colour == RED){
        cout << "出现连续红色节点" << endl;
        return false;
    }
    
  • 验证简单路径下均包含相同数目的黑色结点 :以最左路径作为参考值,当每条路径的黑色节点不等于该基准值时,就违反了红黑树的性质

    bool IsBalance(){
        // 最左路径黑色节点数量做基准值
        int banchmark = 0;
        RBTreeNode* left = _root;
        while (left){
            if (left->_colour == BLACK)
                ++banchmark;
    
            left = left->_left;
        }
        int blackNum = 0;
        return _IsBalance(_root, banchmark, blackNum);
    }
    bool _IsBalance(RBTreeNode* root, int banchmark, int blackNum){
        if (root == nullptr){
            if (banchmark != blackNum){
                cout << "存在路径黑色节点的数量不相等" << endl;
                return false;
            }
            return true;
        }
        if (root->_colour == BLACK){
            ++blackNum;
        }
        return _IsBalance(root->_left, banchmark, blackNum)
            && _IsBalance(root->_right, banchmark, blackNum);
    }
    

4.3 完整代码

bool IsBalance(){
    if (_root && _root->_colour == RED){
        cout << "根节点不是黑色" << endl;
        return false;
    }

    // 最左路径黑色节点数量做基准值
    int banchmark = 0;
    RBTreeNode* left = _root;
    while (left){
        if (left->_colour == BLACK)
            ++banchmark;

        left = left->_left;
    }

    int blackNum = 0;
    return _IsBalance(_root, banchmark, blackNum);
}
bool _IsBalance(RBTreeNode* root, int banchmark, int blackNum){
    if (root == nullptr){
        if (banchmark != blackNum){
            cout << "存在路径黑色节点的数量不相等" << endl;
            return false;
        }
        return true;
    }

    if (root->_colour == RED && root->_parent->_colour == RED){
        cout << "出现连续红色节点" << endl;
        return false;
    }

    if (root->_colour == BLACK){
        ++blackNum;
    }

    return _IsBalance(root->_left, banchmark, blackNum)
        && _IsBalance(root->_right, banchmark, blackNum);
}

五、性能比较

红黑树和AVL树都是高效的平衡二叉树,增删改查的时间复杂度都是O(log2N),红黑树不追求绝对平衡,其只需保证最长路径不超过最短路径的2倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL树更优,而且红黑树实现比较简单,所以实际运用中红黑树更多。

对于AVL树来说,如果高度为h,则节点数量为N = 2^h - 1,高度接近于logN。

对于红黑树来说,虽然左右没有那么均衡,但是整体高度也是可以推断的较为平衡的。假设一条路径下黑色节点数量为X,根据红黑树的性质,假设高度为h,满足于 X ≤ h ≤ 2X,节点数量满足于2^X - 1 ≤ N ≤ 2^2X - 1,分别对应全黑二叉树与一黑一红二叉树。对应的整体高度为2*logN。但是降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL树更优。

六、完整代码

#pragma once
#include 

using namespace std;

enum Colour{
	RED,
	BLACK
};

template<class K, class V>
class RBTreeNode {
public:
	RBTreeNode<K, V>* _left;
	RBTreeNode<K, V>* _right;
	RBTreeNode<K, V>* _parent;

	pair<K, V> _KeyValue;

	Colour _colour;

	RBTreeNode(const pair<K, V>& KeyValue)
		:_left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _colour(RED)
		, _KeyValue(KeyValue)
	{}
};

template<class K,class V>
class RBTree {
	typedef RBTreeNode<K, V> RBTreeNode;
private:
	RBTreeNode* _root;
public:
	RBTree()
		:_root(nullptr)
	{}

	bool Insert(const pair<K, V>& keyValue) {
		// 空树
		if (_root == nullptr) {
			_root = new RBTreeNode(keyValue);
			_root->_colour = BLACK;
			return true;
		}
		// 按搜索树规则查找
		RBTreeNode* parent = nullptr;
		RBTreeNode* cur = _root;
		while (cur) {
			if (cur->_KeyValue.first < keyValue.first) {
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_KeyValue.first > keyValue.first) {
				parent = cur;
				cur = cur->_left;
			}
			else {
				return false;
			}
		}
		// 插入
		cur = new RBTreeNode(keyValue);
		cur->_colour = RED;
		if (parent->_KeyValue.first < keyValue.first) {
			parent->_right = cur;
			cur->_parent = parent;
		}
		else {
			parent->_left = cur;
			cur->_parent = parent;
		}

		// 控制平衡
		while (parent && parent->_colour == RED){
			RBTreeNode* grathfather = parent->_parent;
			if (grathfather->_left == parent) {
				RBTreeNode* uncle = grathfather->_right;
				//父亲节点不为红色且叔叔节点存在且为红
				if (uncle && uncle->_colour == RED) {
					parent->_colour = uncle->_colour = BLACK;
					grathfather->_colour = RED;
					// 迭代
					cur = grathfather;
					parent = cur->_parent;
				}
				//父亲节点不为红色且叔叔节点不存在或存在且为黑
				else {
					// 左左:右单旋
					//		grathfather
					//	  parent
					//  cur
					if (cur == parent->_left) {
						RotateR(grathfather);
						parent->_colour = BLACK;
						grathfather->_colour = RED;
					}
					// 左右:左单旋 -- 右单旋
					//        grathfather
					//     parent
					//        cur
					else {
						RotateL(parent);
						RotateR(grathfather);
						cur->_colour = BLACK;
						grathfather->_colour = RED;
					}
					break;
				}
			}
			else {
				RBTreeNode* uncle = grathfather->_left;
				// 情况一:父亲节点不为红色且叔叔节点存在且为红
				if (uncle && uncle->_colour == RED) {
					parent->_colour = uncle->_colour = BLACK;
					grathfather->_colour = RED;
					// 迭代
					cur = grathfather;
					parent = cur->_parent;
				}
				else {
					// 右右:左单旋
					//		grathfather
					//			parent
					//				cur
					if (cur == parent->_right) {
						RotateL(grathfather);
						parent->_colour = BLACK;
						grathfather->_colour = RED;
					}
					else {
						// 右左:右单旋 -- 左单旋
						//		grathfather
						//			parent
						//		cur
						RotateR(parent);
						RotateL(grathfather);
						cur->_colour = BLACK;
						grathfather->_colour = RED;
					}
					break;
				}
			}
		}
		_root->_colour = BLACK;
	}
	void InOrder(){
		_InOrder(_root);
	}
	bool IsBalance(){
		if (_root && _root->_colour == RED){
			cout << "根节点不是黑色" << endl;
			return false;
		}

		// 最左路径黑色节点数量做基准值
		int banchmark = 0;
		RBTreeNode* left = _root;
		while (left){
			if (left->_colour == BLACK)
				++banchmark;

			left = left->_left;
		}

		int blackNum = 0;
		return _IsBalance(_root, banchmark, blackNum);
	}
private:
	void RotateR(RBTreeNode* parent) {
		RBTreeNode* cur = parent->_left;
		RBTreeNode* curR = cur->_right;
		// 对于parent的parent也要进行连接
		RBTreeNode* parentParent = parent->_parent;

		parent->_left = curR;
		// curR可能为空,因此需要对其进行空指针的判断
		if (curR != nullptr) {
			curR->_parent = parent;
		}

		cur->_right = parent;
		parent->_parent = cur;

		// 如果parent是根节点就不需要连接,将cur作为根
		if (parent == _root) {
			_root = cur;
			_root->_parent == nullptr;
		}
		// 将cur作为根,否则就需要找出链接的子树,并完成相互链接
		else {
			if (parentParent->_left == parent) {
				parentParent->_left = cur;
				cur->_parent = parentParent;
			}
			else {
				parentParent->_right = cur;
				cur->_parent = parentParent;
			}
		}
	}
	void RotateL(RBTreeNode* parent) {
		RBTreeNode* cur = parent->_right;
		RBTreeNode* curL = cur->_left;

		RBTreeNode* parentParent = parent->_parent;

		parent->_right = curL;
		if (curL != nullptr) {
			curL->_parent = parent;
		}

		parent->_parent = cur;
		cur->_left = parent;

		if (parent == _root) {
			_root = cur;
			_root->_parent = nullptr;
		}
		else {
			if (parentParent->_left == parent) {
				parentParent->_left = cur;
				cur->_parent = parentParent;
			}
			else {
				parentParent->_right = cur;
				cur->_parent = parentParent;
			}
		}
	}
	void _InOrder(RBTreeNode* root){
		if (root == NULL)
			return;
		_InOrder(root->_left);
		cout << root->_KeyValue.first << ":" << root->_KeyValue.second << endl;
		_InOrder(root->_right);
	}
	bool _IsBalance(RBTreeNode* root, int banchmark, int blackNum){
		if (root == nullptr){
			if (banchmark != blackNum){
				cout << "存在路径黑色节点的数量不相等" << endl;
				return false;
			}
			return true;
		}

		if (root->_colour == RED && root->_parent->_colour == RED){
			cout << "出现连续红色节点" << endl;
			return false;
		}

		if (root->_colour == BLACK){
			++blackNum;
		}

		return _IsBalance(root->_left, banchmark, blackNum)
			&& _IsBalance(root->_right, banchmark, blackNum);
	}
};

补充:

  1. 代码将会放到:C++/C/数据结构代码链接 ,欢迎查看!
  2. 欢迎各位点赞、评论、收藏与关注,大家的支持是我更新的动力,我会继续不断地分享更多的知识!

你可能感兴趣的:(数据结构,数据结构,算法)