红黑树c++

1.红黑树的概念

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

2.红黑树的性质

1. 每个结点不是红色就是黑色。

2. 根节点是黑色的 。

3. 如果一个节点是红色的,则它的两个孩子结点是黑色的。  

4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点 。

5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)。

3.红黑树节点的定义

enum Colour
{
	RED,
	BLACK
};

template<class T>
struct RBTreeNode
{
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;
	T _value;
	Colour _col;

	RBTreeNode(const T&value=T(),Colour col=RED)
		:_left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _value(value)
		, _col(col)
	{}
};

4.红黑树的结构

为了后续实现关联式容器简单,红黑树的实现中增加一个头结点,因为跟节点必须为黑色,为了 与根节点进行区分,将头结点给成黑色,并且让头结点的 pParent 域指向红黑树的根节点,pLeft 域指向红黑树中最小的节点,_pRight域指向红黑树中最大的节点,如下:

5.红黑树的插入

bool Insert(const T& data)
	{
		Node*& root = GetRoot();
		if (root == nullptr)
		{
			root = new Node(data);
			root->_col = BLACK;
			root->_parent = _pHead;
			_pHead->_left = LeftMost();
			_pHead->_right = RightMost();
			return true;
		}
		Node* cur = root;
		Node* parent = nullptr;
		while (cur)
		{
			if (data > cur->_value)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if(data<cur->_value)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(data);
		if (data > parent->_value)
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_left = cur;
			cur->_parent = parent;
		}
		while (parent!=_pHead&&parent->_col==RED)
		{
				Node* grandparent = parent->_parent;
				if (parent == grandparent->_left)
				{
					Node* uncle = grandparent->_right;
					//情况一
					if (uncle && uncle->_col == RED)//uncle存在且为红
					{
						uncle->_col = parent->_col = BLACK;
						grandparent->_col = RED;
						cur = grandparent;
						parent = cur->_parent;
					}
					else//uncle不存在
					{
						//情况三后转为情况二
						if (cur == parent->_right)
						{
							RotateL(parent);
							swap(parent, cur);
						}
						//情况二
						RotateR(grandparent);
						parent->_col = BLACK;
						grandparent->_col = RED; 
					}
				}
				else if (parent == grandparent->_right)
				{
					Node* uncle = grandparent->_left;
					//情况一
					if (uncle && uncle->_col == RED)//uncle存在且为红
					{
						uncle->_col = parent->_col = BLACK;
						grandparent->_col = RED;
						cur = grandparent;
						parent = cur->_parent;
					}
					else//uncle不存在
					{
						//情况三后转为情况二
						if (cur == parent->_left)
						{
							RotateR(parent);
							swap(parent, cur);
						}
						//情况二
						RotateL(grandparent);
						parent->_col = BLACK;
						grandparent->_col = RED;
					}
				}
		}
		root->_col = BLACK;
		_pHead->_left = LeftMost();
		_pHead->_right = RightMost();
		return true;
	}

	// 右单旋
	void RotateR(Node* pParent)
	{
		Node* root = GetRoot();
		Node* subL = pParent->_left;
		Node* subLR = subL->_right;
		Node* grandparent = pParent->_parent;
		pParent->_left = subLR;
		if (subLR)
		{
			subLR->_parent = pParent;
		}
		subL->_right = pParent;
		pParent->_parent = subL;

		if (root == pParent)
		{
			root = subL;
			subL->_parent = _pHead;
			_pHead->_parent = root;
		}
		else
		{
			if (pParent == grandparent->_left)
			{
				grandparent->_left = subL;
			}
			else
			{
				grandparent->_right = subL;
			}
			subL->_parent = grandparent;
		}
	}

	// 左单旋
	void RotateL(Node* pParent)
	{
		Node* root = GetRoot();
		Node* subR = pParent->_right;
		Node* subRL = subR->_left;
		Node* grandparent = pParent->_parent;
		pParent->_right = subRL;
		if (subRL)
		{
			subRL->_parent = pParent;
		}
		subR->_left = pParent;
		pParent->_parent = subR;
		if (root == pParent)
		{
			root = subR;
			subR->_parent = _pHead;
			_pHead->_parent = root;
		}
		else
		{
			if (pParent == grandparent->_left)
			{
				grandparent->_left = subR;
			}
			else
			{
				grandparent->_right = subR;
			}
			subR->_parent = grandparent;
		}
	}
// 获取红黑树最左侧节点
	Node* LeftMost()
	{
		Node* cur = GetRoot();
		if (!cur) return _pHead;
		Node* parent = nullptr;
		while (cur)
		{
			parent = cur;
			cur = cur->_left;
		}
		return parent;
	}

	// 获取红黑树最右侧节点
	Node* RightMost()
	{
		Node* cur = GetRoot();
		if (!cur) return _pHead;
		Node* parent = nullptr;
		while (cur)
		{
			parent = cur;
			cur = cur->_right;
		}
		return parent;
	}

6.红黑树的验证

红黑树的检测分为两步:

1. 检测其是否满足二叉搜索树(中序遍历是否为有序序列)。

2. 检测其是否满足红黑树的性质。

void InOrder()
	{
		_InOrder(GetRoot());
		cout << endl;
	}

	void _InOrder(Node* root)
	{
		if (root == nullptr)
			return;

		_InOrder(root->_left);
		cout << root->_value << " ";
		_InOrder(root->_right);
	}
// 检测红黑树是否为有效的红黑树,注意:其内部主要依靠_IsValidRBTRee函数检测
	bool IsValidRBTRee()
	{
		Node* root = GetRoot();
		if (root == nullptr)
		{
			return true;
		}
		if (root->_col != BLACK)
		{
			cout << "违反性质二:根节点是黑色" << endl;
		}
		//一条路径的黑色节点个数
		size_t pathBlack = 0;
		Node* cur = root;
		while (cur)
		{
			if (cur->_col == BLACK)
			{
				pathBlack++;
			}
			cur = cur->_left;
		}
		size_t blackCount = 0;
		
		return _IsValidRBTRee(GetRoot(), blackCount, pathBlack);
	}
private:
	//根节点,黑色节点个数,路径中黑色节点个数
	bool _IsValidRBTRee(Node* pRoot, size_t blackCount,const size_t pathBlack)
	{
		if (pRoot == nullptr)
		{
			if (blackCount != pathBlack)
			{
				cout << "pathBlack:" << pathBlack << endl;
				cout << "blackCount:" << blackCount << endl;
				cout << "违反性质四:每条路径都包含相同的黑色节点" << endl;
				return false;
			}
			return true;
		}
		if (pRoot->_col == BLACK)
			blackCount++;
		Node* parent = pRoot->_parent;
		if (pRoot->_col == RED)
		{
			if (parent&&parent->_col==RED)
			{
				cout << "违反性质三:不能有连续的红色节点" << endl;
				return false;
			}
		}
		return _IsValidRBTRee(pRoot->_left, blackCount, pathBlack) &&
			_IsValidRBTRee(pRoot->_right, blackCount, pathBlack);
	}
	// 为了操作树简单起见:获取根节点
	Node*& GetRoot()
	{
		return _pHead->_parent;
	}

完整代码如下:

#pragma once
#include<iostream>
using namespace std;

enum Colour
{
	RED,
	BLACK
};

template<class T>
struct RBTreeNode
{
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;
	T _value;
	Colour _col;

	RBTreeNode(const T&value=T(),Colour col=RED)
		:_left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _value(value)
		, _col(col)
	{}
};



// 请模拟实现红黑树的插入--注意:为了后序封装map和set,本文在实现时给红黑树多增加了一个头结点
template<class T>
class RBTree
{
	typedef RBTreeNode<T> Node;
public:
	RBTree()
	{
		_pHead = new Node;
		_pHead->_left = _pHead;
		_pHead->_right = _pHead;
	}

	// 在红黑树中插入值为data的节点,插入成功返回true,否则返回false
	// 注意:为了简单起见,本次实现红黑树不存储重复性元素
	bool Insert(const T& data)
	{
		Node*& root = GetRoot();
		if (root == nullptr)
		{
			root = new Node(data);
			root->_col = BLACK;
			root->_parent = _pHead;
			_pHead->_left = LeftMost();
			_pHead->_right = RightMost();
			return true;
		}
		Node* cur = root;
		Node* parent = nullptr;
		while (cur)
		{
			if (data > cur->_value)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if(data<cur->_value)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(data);
		if (data > parent->_value)
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_left = cur;
			cur->_parent = parent;
		}
		while (parent!=_pHead&&parent->_col==RED)
		{
				Node* grandparent = parent->_parent;
				if (parent == grandparent->_left)
				{
					Node* uncle = grandparent->_right;
					//情况一
					if (uncle && uncle->_col == RED)//uncle存在且为红
					{
						uncle->_col = parent->_col = BLACK;
						grandparent->_col = RED;
						cur = grandparent;
						parent = cur->_parent;
					}
					else//uncle不存在
					{
						//情况三后转为情况二
						if (cur == parent->_right)
						{
							RotateL(parent);
							swap(parent, cur);
						}
						//情况二
						RotateR(grandparent);
						parent->_col = BLACK;
						grandparent->_col = RED; 
					}
				}
				else if (parent == grandparent->_right)
				{
					Node* uncle = grandparent->_left;
					//情况一
					if (uncle && uncle->_col == RED)//uncle存在且为红
					{
						uncle->_col = parent->_col = BLACK;
						grandparent->_col = RED;
						cur = grandparent;
						parent = cur->_parent;
					}
					else//uncle不存在
					{
						//情况三后转为情况二
						if (cur == parent->_left)
						{
							RotateR(parent);
							swap(parent, cur);
						}
						//情况二
						RotateL(grandparent);
						parent->_col = BLACK;
						grandparent->_col = RED;
					}
				}
		}
		root->_col = BLACK;
		_pHead->_left = LeftMost();
		_pHead->_right = RightMost();
		return true;
	}

	// 右单旋
	void RotateR(Node* pParent)
	{
		Node* root = GetRoot();
		Node* subL = pParent->_left;
		Node* subLR = subL->_right;
		Node* grandparent = pParent->_parent;
		pParent->_left = subLR;
		if (subLR)
		{
			subLR->_parent = pParent;
		}
		subL->_right = pParent;
		pParent->_parent = subL;

		if (root == pParent)
		{
			root = subL;
			subL->_parent = _pHead;
			_pHead->_parent = root;
		}
		else
		{
			if (pParent == grandparent->_left)
			{
				grandparent->_left = subL;
			}
			else
			{
				grandparent->_right = subL;
			}
			subL->_parent = grandparent;
		}
	}

	// 左单旋
	void RotateL(Node* pParent)
	{
		Node* root = GetRoot();
		Node* subR = pParent->_right;
		Node* subRL = subR->_left;
		Node* grandparent = pParent->_parent;
		pParent->_right = subRL;
		if (subRL)
		{
			subRL->_parent = pParent;
		}
		subR->_left = pParent;
		pParent->_parent = subR;
		if (root == pParent)
		{
			root = subR;
			subR->_parent = _pHead;
			_pHead->_parent = root;
		}
		else
		{
			if (pParent == grandparent->_left)
			{
				grandparent->_left = subR;
			}
			else
			{
				grandparent->_right = subR;
			}
			subR->_parent = grandparent;
		}
	}


	// 检测红黑树中是否存在值为data的节点,存在返回该节点的地址,否则返回nullptr
	Node* Find(const T& data)
	{
		if (GetRoot() == nullptr) return nullptr;
		Node* cur = GetRoot();
		while (cur)
		{
			if (cur->_value > data)
			{
				cur = cur->_left;
			}
			else if (cur->_value < data)
			{
				cur = cur->_right;
			}
			else
			{
				return cur;
			}
		}
		return nullptr;
	}

	void InOrder()
	{
		_InOrder(GetRoot());
		cout << endl;
	}

	void _InOrder(Node* root)
	{
		if (root == nullptr)
			return;

		_InOrder(root->_left);
		cout << root->_value << " ";
		_InOrder(root->_right);
	}

	// 获取红黑树最左侧节点
	Node* LeftMost()
	{
		Node* cur = GetRoot();
		if (!cur) return _pHead;
		Node* parent = nullptr;
		while (cur)
		{
			parent = cur;
			cur = cur->_left;
		}
		return parent;
	}

	// 获取红黑树最右侧节点
	Node* RightMost()
	{
		Node* cur = GetRoot();
		if (!cur) return _pHead;
		Node* parent = nullptr;
		while (cur)
		{
			parent = cur;
			cur = cur->_right;
		}
		return parent;
	}

	// 检测红黑树是否为有效的红黑树,注意:其内部主要依靠_IsValidRBTRee函数检测
	bool IsValidRBTRee()
	{
		Node* root = GetRoot();
		if (root == nullptr)
		{
			return true;
		}
		if (root->_col != BLACK)
		{
			cout << "违反性质二:根节点是黑色" << endl;
		}
		//一条路径的黑色节点个数
		size_t pathBlack = 0;
		Node* cur = root;
		while (cur)
		{
			if (cur->_col == BLACK)
			{
				pathBlack++;
			}
			cur = cur->_left;
		}
		size_t blackCount = 0;
		
		return _IsValidRBTRee(GetRoot(), blackCount, pathBlack);
	}
private:
	//根节点,黑色节点个数,路径中黑色节点个数
	bool _IsValidRBTRee(Node* pRoot, size_t blackCount,const size_t pathBlack)
	{
		if (pRoot == nullptr)
		{
			if (blackCount != pathBlack)
			{
				cout << "pathBlack:" << pathBlack << endl;
				cout << "blackCount:" << blackCount << endl;
				cout << "违反性质四:每条路径都包含相同的黑色节点" << endl;
				return false;
			}
			return true;
		}
		if (pRoot->_col == BLACK)
			blackCount++;
		Node* parent = pRoot->_parent;
		if (pRoot->_col == RED)
		{
			if (parent&&parent->_col==RED)
			{
				cout << "违反性质三:不能有连续的红色节点" << endl;
				return false;
			}
		}
		return _IsValidRBTRee(pRoot->_left, blackCount, pathBlack) &&
			_IsValidRBTRee(pRoot->_right, blackCount, pathBlack);
	}
	// 为了操作树简单起见:获取根节点
	Node*& GetRoot()
	{
		return _pHead->_parent;
	}
private:
	//_pHead与root互为parent节点,并且_pHead左右指向最左右两端的节点
	Node* _pHead;
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Sakura&NANA

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

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

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

打赏作者

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

抵扣说明:

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

余额充值