红黑树的概念及其基本操作

1.红黑树的概念

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

2.红黑树的性质

  • 每个节点不是红色就是黑色
  • 根结点是黑色的
  • 如果一个节点是红色的,则它的两个孩子都是黑色的
  • 每条路径上的黑色结点数目相同
  • 每个叶子结点都是黑色的(这里的叶子结点指的是空节点)

3.红黑树结点的定义

enum Color{RED,BLACK};
template<class T>
struct RBTreeNode {
	RBTreeNode(const T&data=T(),Color color= RED)
		:_pLeft(nullptr)
		,_pRight(nullptr)
		,_pParent(nullptr)
		,_data(data)
		,_color(color)
	{}
	RBTreeNode<T>* _pLeft;
	RBTreeNode<T>* _pRight;
	RBTreeNode<T>* _pParent;
	Color _color;
	T _data;
};

4.红黑树的插入操作

红黑树是在二叉搜索树的基础上加上其平衡限制条件,因此,红黑树的插入可分为两步
(1):按照二叉搜索树的规则插入新节点

bool Insert(const T& data) {
		Node*& pRoot = GetRoot();
		if (pRoot == nullptr) {
			pRoot = new Node(data, BLACK);
			pRoot->_pParent = _pHead;
			return true;
		}
		else {
			Node* pCur = pRoot;
			Node* pParent = nullptr;
			while (pCur) {
				pParent = pCur;
				if (data < pCur->_data) {
					pCur = pCur->_pLeft;
				}
				else if (data > pCur->_data) {
					pCur = pCur->_pRight;
				}
				else {
					return false;
				}
			}
			pCur = new Node(data);
			if (data < pParent->_data) {
				pParent->_pLeft = pCur;
			}
			else {
				pParent->_pRight = pCur;
			}
			pCur->_pParent = pParent;

(2):检测新节点插入后,红黑树的心智是否遭到破坏

	while (pParent != _pHead && pParent->_color == RED) {
				Node* grandfather = pParent->_pParent;
				if (pParent == grandfather->_pLeft) {
					Node* uncle = grandfather->_pRight;
					if (uncle && uncle->_color == RED) {
						uncle->_color = BLACK;
						pParent->_color = BLACK;
						grandfather->_color = RED;
						pCur = grandfather;
						pParent = pCur->_pParent;
					}
					else {
						if (pCur == pParent->_pRight) {
							RotateL(pParent);
							swap(pCur, pParent);
						}
						pParent->_color = BLACK;
						grandfather->_color = RED;
						RotateR(grandfather);
					}
				}
				else {
					Node* uncle = grandfather->_pLeft;
					if (uncle && uncle->_color == RED) {
						uncle->_color = BLACK;
						pParent->_color = BLACK;
						grandfather->_color = RED;
						pCur = grandfather;
						pParent = pCur->_pParent;
					}
					else {
						if (pCur == pParent->_pLeft) {
							RotateR(pParent);
							swap(pParent, pCur);
						}
						pParent->_color = BLACK;
						grandfather->_color = RED;
						RotateL(grandfather);
					}
				}
			}
		}

5.红黑树的验证

  • 检测其是否满足二叉搜索树(中序遍历是否为有序遍历)
	Node* _InOrder(Node* pRoot) {
		if (pRoot) {
			_InOrder(pRoot->_pLeft);
			cout << pRoot->_data << " ";
			_InOrder(pRoot->_pRight);
		}
		return pRoot;
	}
  • 检测其是否满足红黑树的性质
	bool IsvalidRBTree() {
		Node* pRoot = GetRoot();
		if (pRoot == nullptr) {
			return true;
		}
		if (pRoot->_color != BLACK) {
			cout << "违反了性质一" << endl;
			return false;
		}
		int blackCount = 0;
		Node* pCur = pRoot;
		while (pCur) {
			if (pCur->_color == BLACK) {
				blackCount++;
			}
			pCur = pCur->_pLeft;
		}
		size_t pathblack = 0;
		return _IsvalidRBTree(pRoot, blackCount, pathblack);
	}
private:
	bool _IsvalidRBTree(Node* pRoot, size_t blackCount, size_t pathblack) {
		if (pRoot == nullptr) {
			return true;
		}
		if (pRoot->_color == BLACK) {
			pathblack++;
		}
		if (nullptr == pRoot->_pLeft && nullptr == pRoot->_pRight) {
			if (pathblack != blackCount) {
				cout << "违反性质四:每条路径上的黑色结点个数相同" << endl;
				return false;
			}
		}
		Node* pParent = pRoot->_pParent;
		if (pParent != _pHead && pParent->_color == RED && pRoot->_color == RED) {
			cout << "违反性质三:红色结点不能连在一起" << endl;
			return false;
		}
		return _IsvalidRBTree(pRoot->_pLeft,blackCount,pathblack) && _IsvalidRBTree(pRoot->_pRight,blackCount,pathblack);
	}

6.红黑树的完整代码

enum Color{RED,BLACK};
template<class T>
struct RBTreeNode {
	RBTreeNode(const T&data=T(),Color color= RED)
		:_pLeft(nullptr)
		,_pRight(nullptr)
		,_pParent(nullptr)
		,_data(data)
		,_color(color)
	{}
	RBTreeNode<T>* _pLeft;
	RBTreeNode<T>* _pRight;
	RBTreeNode<T>* _pParent;
	Color _color;
	T _data;
};
template<class T>
class RBTree {
	typedef RBTreeNode<T>Node;
public:
	RBTree() {
		_pHead = new Node;
		_pHead->_pLeft = _pHead;
		_pHead->_pRight = _pHead;
	}
	bool Insert(const T& data) {
		Node*& pRoot = GetRoot();
		if (pRoot == nullptr) {
			pRoot = new Node(data, BLACK);
			pRoot->_pParent = _pHead;
			return true;
		}
		else {
			Node* pCur = pRoot;
			Node* pParent = nullptr;
			while (pCur) {
				pParent = pCur;
				if (data < pCur->_data) {
					pCur = pCur->_pLeft;
				}
				else if (data > pCur->_data) {
					pCur = pCur->_pRight;
				}
				else {
					return false;
				}
			}
			pCur = new Node(data);
			if (data < pParent->_data) {
				pParent->_pLeft = pCur;
			}
			else {
				pParent->_pRight = pCur;
			}
			pCur->_pParent = pParent;
			while (pParent != _pHead && pParent->_color == RED) {
				Node* grandfather = pParent->_pParent;
				if (pParent == grandfather->_pLeft) {
					Node* uncle = grandfather->_pRight;
					if (uncle && uncle->_color == RED) {
						uncle->_color = BLACK;
						pParent->_color = BLACK;
						grandfather->_color = RED;
						pCur = grandfather;
						pParent = pCur->_pParent;
					}
					else {
						if (pCur == pParent->_pRight) {
							RotateL(pParent);
							swap(pCur, pParent);
						}
						pParent->_color = BLACK;
						grandfather->_color = RED;
						RotateR(grandfather);
					}
				}
				else {
					Node* uncle = grandfather->_pLeft;
					if (uncle && uncle->_color == RED) {
						uncle->_color = BLACK;
						pParent->_color = BLACK;
						grandfather->_color = RED;
						pCur = grandfather;
						pParent = pCur->_pParent;
					}
					else {
						if (pCur == pParent->_pLeft) {
							RotateR(pParent);
							swap(pParent, pCur);
						}
						pParent->_color = BLACK;
						grandfather->_color = RED;
						RotateL(grandfather);
					}
				}
			}
		}
		pRoot->_color = BLACK;
		_pHead->_pLeft = LeftMost();
		_pHead->_pRight = RightMost();
		return true;
	}
	void InOrder() {
		_InOrder(GetRoot());
	}
	Node* LeftMost() {
		Node* pRoot = GetRoot();
		if (pRoot == nullptr) {
			return NULL;
		}
		Node* pCur = pRoot;
		while (pCur->_pLeft) {
			pCur = pCur->_pLeft;
		}
		return pCur;
	}
	Node* RightMost() {
		Node* pRoot = GetRoot();
		if (pRoot == nullptr) {
			return NULL;
		}
		Node* pCur = pRoot;
		while (pCur->_pRight) {
			pCur = pCur->_pRight;
		}
		return pCur;
	}
	bool IsvalidRBTree() {
		Node* pRoot = GetRoot();
		if (pRoot == nullptr) {
			return true;
		}
		if (pRoot->_color != BLACK) {
			cout << "违反了性质一" << endl;
			return false;
		}
		int blackCount = 0;
		Node* pCur = pRoot;
		while (pCur) {
			if (pCur->_color == BLACK) {
				blackCount++;
			}
			pCur = pCur->_pLeft;
		}
		size_t pathblack = 0;
		return _IsvalidRBTree(pRoot, blackCount, pathblack);
	}
private:
	bool _IsvalidRBTree(Node* pRoot, size_t blackCount, size_t pathblack) {
		if (pRoot == nullptr) {
			return true;
		}
		if (pRoot->_color == BLACK) {
			pathblack++;
		}
		if (nullptr == pRoot->_pLeft && nullptr == pRoot->_pRight) {
			if (pathblack != blackCount) {
				cout << "违反性质四:每条路径上的黑色结点个数相同" << endl;
				return false;
			}
		}
		Node* pParent = pRoot->_pParent;
		if (pParent != _pHead && pParent->_color == RED && pRoot->_color == RED) {
			cout << "违反性质三:红色结点不能连在一起" << endl;
			return false;
		}
		return _IsvalidRBTree(pRoot->_pLeft,blackCount,pathblack) && _IsvalidRBTree(pRoot->_pRight,blackCount,pathblack);
	}
	void RotateL(Node* pParent) {
		Node* pSubR = pParent->_pRight;
		Node* pSubRL = pSubR->_pLeft;
		pParent->_pRight = pSubRL;
		if (pSubRL) {
			pSubRL->_pParent = pParent;
		}
		pSubR->_pLeft = pParent;
		Node* pPParent = pParent->_pParent;
		pParent->_pParent = pSubR;
		pSubR->_pParent = pPParent;
		if (pPParent == _pHead) {
			_pHead->_pParent=pSubR;
		}
		else {
			if (pPParent->_pLeft == pParent) {
				pPParent->_pLeft = pSubR;
			}
			else {
				pPParent->_pRight = pSubR;
			}
		}
	}
	void RotateR(Node* pParent) {
		Node* pSubL = pParent->_pLeft;
		Node*pSubLR = pSubL->_pRight;
		pParent->_pLeft = pSubLR;
		if (pSubLR) {
			pSubLR->_pParent = pParent;
		}
		pSubL->_pRight = pParent;
		Node* pPParent = pParent->_pParent;
		pParent->_pParent = pSubL;
		pSubL->_pParent = pPParent;
		if (pPParent == _pHead) {
			_pHead->_pParent = pSubL;
		}
		else {
			if (pPParent->_pLeft == pParent) {
				pPParent->_pLeft = pSubL;
			}
			else {
				pPParent->_pRight = pSubL;
			}
		}
	}
	Node*& GetRoot() {
		return _pHead->_pParent;
	}
	Node* _InOrder(Node* pRoot) {
		if (pRoot) {
			_InOrder(pRoot->_pLeft);
			cout << pRoot->_data << " ";
			_InOrder(pRoot->_pRight);
		}
		return pRoot;
	}
private:
	Node* _pHead;
};
void TestRBTree() {
	int a[] = { 5, 3, 4 ,1, 7, 8, 2, 6, 0, 9 };
	RBTree<int>t;
	for (auto e : a) {
		t.Insert(e);
	}
	t.InOrder();
	cout << endl;
	cout << t.LeftMost()->_data << endl;
	cout << t.RightMost()->_data << endl;
	if (t.IsvalidRBTree()) {
		cout << "is RBTree" << endl;
	}
	else {
		cout << "is not RBTree" << endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值