红黑树的插入

2 篇文章 0 订阅

3.红黑树

3.1概念

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

image-20240730115620218

3.2 性质

  1. 每个结点不是红色就是黑色
  2. 根节点是黑色的
  3. 如果一个节点是红色的,则它的两个孩子结点是黑色的, 说明树里面不能出现连续的红色节点
  4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点
  5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点), 这个性质是为了方便数树有几条路径

问题: 为什么满足上面的性质,红黑树就能保证:其最长路径中节点个数不会超过最短路径节点个数的两倍?

解答: 根据性质3和性质4可知, 如果有一颗红黑树, 那么它的最短路径应是全黑节点, 最长路径应是一红一黑节点交替
于是, 我们可以得到一个结论, 假设每条路径有N个黑色节点, 那么每条路径的节点个数为[N, 2N]. 这样就满足了问题红黑树的特征, 即
最长路径中节点个数不会超过最短路径节点个数的两倍

3.3 RBTree的实现

3.3.1 insert的框架

与前面的avl树类似

#pragma once
enum Color
{
	RED,
	BLACK
};

template<class K, class V>
struct RBTreeNode
{
	RBTreeNode(const pair<K, V>& kv) : _kv(kv), _left(nullptr)
		, _right(nullptr), _parent(nullptr), _bf(RED) {}

	RBTreeNode<K, V>* _left;
	RBTreeNode<K, V>* _right;
	RBTreeNode<K, V>* _parent;
	pair<K, V> _kv;
	Color _color;
};

template<class K, class V>
class RBTree
{
	typedef RBTreeNode<K, V> Node;
public:
	bool insert(const pair<K, V>& kv)
	{
		// a. 树为空,则直接新增节点,赋值给root指针
		if (_root == nullptr) {
			_root = new Node(kv);
			// 根节点是黑色的
			_root->_color = BLACK;
			return true;
		}
		// b. 树不空,按二叉搜索树性质查找插入位置,插入新节点
		Node* cur = _root, * parent = nullptr;
		while (cur) {
			if (cur->_kv.first < kv.first) {
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_kv.first > kv.first) {
				parent = cur;
				cur = cur->_left;
			}
			else return false;
		}
		// cur为空,找到了一个合适的位置,此时需要链接,注意链接位置
		cur = new Node(kv);
		// cur->_color = ?? 
		if (kv.first < parent->_kv.first) {
			parent->_left = cur;
			cur->_parent = parent;
		}
		else {
			parent->_right = cur;
			cur->_parent = parent;
		}

		// new code....

		return true;
	}
private:
	Node* _root = nullptr;
};

3.3.2 insert的处理

新增节点, 选择红色, 因为黑色会影响其他路径

  1. 新增节点的父亲是黑色的, 不需要处理
  2. 新增节点的父亲是红色的, 需要处理
    (变色)or(变色+旋转)

规定cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点

情况1: cur为红,p为红,g为黑, u 存在且为红 \textcolor{red}{u存在且为红} u存在且为红

image-20240731121943681

while (parent && parent->_color == RED) {
	Node* grandparent = parent->_parent;
	if (parent == grandparent->_left) {
		Node* uncle = grandparent->_right;
		// uncle存在且为红, 情况1
		if (uncle && uncle->_color == RED) {
			//        g(b)
			//     p(r)  u(r)
			//  c(r)
			// 变色
			parent->_color = uncle->_color = BLACK;
			grandparent->_color = RED;
			// 继续向上处理
			cur = grandparent;
			parent = cur->_parent;
		}
	}
}
// 处理后_root可能会变色, 在这里它置为黑色
_root = BLACK;

情况2:cur为红,p为红,g为黑, u 不存在 / u 存在且为黑 \textcolor{red}{u不存在/u存在且为黑} u不存在/u存在且为黑

image-20240805162910573

while (parent && parent->_color == RED) {
	Node* grandparent = parent->_parent;
	if (parent == grandparent->_left) {
		Node* uncle = grandparent->_right;
		// uncle存在且为红, 情况1
		if (uncle && uncle->_color == RED) {
			//        g(b)
			//     p(r)  u(r)
			//  c(r)
			// 变色
			parent->_color = uncle->_color = BLACK;
			grandparent->_color = RED;
			// 继续向上处理
			cur = grandparent;
			parent = cur->_parent;
		}
		// uncle为黑或者不存在
		else {
			// cur在parent的左边, 情况2, 单旋
			if (cur = parent->_left) {
				//        g(b)
				//     p(r)  u(b)
				//  c(r)
				RotateR(grandparent);
				parent->_color = BLACK;
				grandparent->_color = RED;
			}
			break;
		}
	}
}
// 处理后_root可能会变色, 在这里它置为黑色
_root = BLACK;

情况3:cur为红,p为红,g为黑, u 不存在 / u 存在且为黑 \textcolor{red}{u不存在/u存在且为黑} u不存在/u存在且为黑, cur的位置与前面不同

image-20240805171707446

while (parent && parent->_color == RED) {
	Node* grandparent = parent->_parent;
	if (parent == grandparent->_left) {
		Node* uncle = grandparent->_right;
		// uncle存在且为红, 情况1
		if (uncle && uncle->_color == RED) {
			//        g(b)
			//     p(r)  u(r)
			//  c(r)
			// 变色
			parent->_color = uncle->_color = BLACK;
			grandparent->_color = RED;
			// 继续向上处理
			cur = grandparent;
			parent = cur->_parent;
		}
		// uncle为黑或者不存在
		else {
			// cur在parent的左边, 情况2, 单旋
			if (cur = parent->_left) {
				//        g(b)
				//     p(r)  u(b)
				//  c(r)
				RotateR(grandparent);
				parent->_color = BLACK;
				grandparent->_color = RED;
			}
            // cur在parent的右边, 情况3, 双旋
            else {
                //         g(b)
                //     p(r)    u(b)
                //		   c(r)
                RotateL(parent);
                RotateR(grandparent);
                cur->_color = BLACK;
                grandparent->_color = RED;
            }
			break;
		}
	}
}
// 处理后_root可能会变色, 在这里它置为黑色
_root = BLACK;

完善else条件

while (parent && parent->_color == RED) {
	Node* grandparent = parent->_parent;
	if (parent == grandparent->_left) {
		Node* uncle = grandparent->_right;
		// uncle存在且为红, 情况1
		if (uncle && uncle->_color == RED) {
			//        g(b)
			//     p(r)  u(r)
			//  c(r)
			// 变色
			parent->_color = uncle->_color = BLACK;
			grandparent->_color = RED;
			// 继续向上处理
			cur = grandparent;
			parent = cur->_parent;
		}
		// uncle为黑或者不存在
		else {
			// cur在parent的左边, 情况2, 单旋
			if (cur = parent->_left) {
				//        g(b)
				//     p(r)  u(b)
				//  c(r)
				RotateR(grandparent);
				parent->_color = BLACK;
				grandparent->_color = RED;
			}
			// cur在parent的右边, 情况3, 双旋
			else {
				//         g(b)
				//     p(r)    u(b)
				//		   c(r)
				RotateL(parent);
				RotateR(grandparent);
				cur->_color = BLACK;
				grandparent->_color = RED;
			}
			break;
		}
	}
	// parent == grandparent->_right
	else {
		// uncle存在且为红, 情况1
		if (uncle && uncle->_color == RED) {
			//        g(b)
			//    u(r)   p(r)
			//               c(r)
			// 变色
			parent->_color = uncle->_color = BLACK;
			grandparent->_color = RED;
			// 继续向上处理
			cur = grandparent;
			parent = cur->_parent;
		}
		// uncle为黑或者不存在
		else {
			// cur在parent的右边, 情况2, 单旋
			if (cur = parent->_right) {
				//        g(b)
				//     u(b)  p(r)
				//			      c(r)
				RotateL(grandparent);
				parent->_color = BLACK;
				grandparent->_color = RED;
			}
			// cur在parent的右边, 情况3, 双旋
			else {
				//         g(b)
				//     u(r)    p(b)
				//		   c(r)
				RotateR(parent);
				RotateL(grandparent);
				cur->_color = BLACK;
				grandparent->_color = RED;
			}
			break;
		}
	}
}
// 处理后_root可能会变色, 在这里它置为黑色
_root = BLACK;
return true;

3.3.3 中序遍历

void InOrder()
{
	_InOrder(_root);
	cout << endl;
}
void _InOrder(Node* root)
{
	if (root == nullptr)	return;
	_InOrder(root->_left);
	cout << root->_kv.first << ' ';
	_InOrder(root->_right);
}

3.3.4检查是否平衡和获取树的高度

bool IsBalance()
{
	if (_root == nullptr)	return true;
	// 违反规则2
	if (_root->_color == RED)	return false;

	int refVal = 0;		// 参考值, 记录某一条路径上的黑色节点的数量
	Node* cur = _root;
	while (cur) {
		if (cur->_color == BLACK)
			refVal++;
		cur = cur->_left;
	}
	int blackNum = 0;

	return Check(_root, refVal, blackNum);
}

bool Check(Node* root, const int& refVal, int blackNum)
{
	if (root == nullptr) { 
		// cout << blackNum << endl;
		if(blackNum == refVal)
			return true; 
		else {
			cout << "有路径黑色节点数量不一致" << endl;
			return false;
		}
	}
	if (root->_color == BLACK)	blackNum++;
	if (root->_color == RED && root->_parent->_color == RED) {
		// 违反规则3
		cout << "有连续的红色节点" << endl;
		return false;
	}
	
	return Check(root->_left, refVal, blackNum) 
		&& Check(root->_right, refVal, blackNum);
}
int GetHeight()
{
	return _GetHeight(_root);
}
int _GetHeight(Node* root)
{
	if (root == nullptr)	return 0;
	int left = _GetHeight(root->_left);
	int right = _GetHeight(root->_right);
	return left > right ? left + 1 : right + 1;
}

3.4完整代码

#pragma once
#include <iostream>
#include <vector>
using namespace std;
enum Color
{
	RED,
	BLACK
};

template<class K, class V>
struct RBTreeNode
{
	RBTreeNode(const pair<K, V>& kv) : _kv(kv), _left(nullptr)
		, _right(nullptr), _parent(nullptr), _color(RED) {}

	RBTreeNode<K, V>* _left;
	RBTreeNode<K, V>* _right;
	RBTreeNode<K, V>* _parent;
	pair<K, V> _kv;
	Color _color;
};

template<class K, class V>
class RBTree
{
	typedef RBTreeNode<K, V> Node;
public:
	bool insert(const pair<K, V>& kv)
	{
		// a. 树为空,则直接新增节点,赋值给root指针
		if (_root == nullptr) {
			_root = new Node(kv);
			// 根节点是黑色的
			_root->_color = BLACK;
			return true;
		}
		// b. 树不空,按二叉搜索树性质查找插入位置,插入新节点
		Node* cur = _root, *parent = nullptr;
		while (cur) {
			if (cur->_kv.first < kv.first) {
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_kv.first > kv.first) {
				parent = cur;
				cur = cur->_left;
			}
			else return false;
		}
		// cur为空,找到了一个合适的位置,此时需要链接,注意链接位置
		cur = new Node(kv);
		cur->_color = RED;		// 新增节点给红色
		if (parent->_kv.first < kv.first) {
			parent->_right = cur;
			cur->_parent = parent;
		}
		else {
			parent->_left = cur;
			cur->_parent = parent;
		}

		while (parent && parent->_color == RED) {
			Node* grandparent = parent->_parent;
			if (parent == grandparent->_left) {
				Node* uncle = grandparent->_right;
				// uncle存在且为红, 情况1
				if (uncle && uncle->_color == RED) {
					//        g(b)
					//     p(r)  u(r)
					//  c(r)
					// 变色
					parent->_color = uncle->_color = BLACK;
					grandparent->_color = RED;
					// 继续向上处理
					cur = grandparent;
					parent = cur->_parent;
				}
				// uncle为黑或者不存在
				else {
					// cur在parent的左边, 情况2, 单旋
					if (cur == parent->_left) {
						//        g(b)
						//     p(r)  u(b)
						//  c(r)
						RotateR(grandparent);
						parent->_color = BLACK;
						grandparent->_color = RED;
					}
					// cur在parent的右边, 情况3, 双旋
					else {
						//         g(b)
						//     p(r)    u(b)
						//		   c(r)
						RotateL(parent);
						RotateR(grandparent);
						cur->_color = BLACK;
						grandparent->_color = RED;
					}
					break;
				}
			}
			// parent == grandparent->_right
			else {
				Node* uncle = grandparent->_left;
				// uncle存在且为红, 情况1
				if (uncle && uncle->_color == RED) {
					//        g(b)
					//    u(r)   p(r)
					//               c(r)
					// 变色
					parent->_color = uncle->_color = BLACK;
					grandparent->_color = RED;
					// 继续向上处理
					cur = grandparent;
					parent = cur->_parent;
				}
				// uncle为黑或者不存在
				else {
					// cur在parent的右边, 情况2, 单旋
					if (cur == parent->_right) {
						//        g(b)
						//     u(b)  p(r)
						//			      c(r)
						RotateL(grandparent);
						parent->_color = BLACK;
						grandparent->_color = RED;
					}
					// cur在parent的左边, 情况3, 双旋
					else {
						//         g(b)
						//     u(r)    p(b)
						//		   c(r)
						RotateR(parent);
						RotateL(grandparent);
						cur->_color = BLACK;
						grandparent->_color = RED;
					}
					break;
				}
			}
		}
		// 处理后_root可能会变色, 在这里它置为黑色
		_root->_color = BLACK;
		return true;
	}

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

	bool IsBalance()
	{
		if (_root == nullptr)	return true;
		// 违反规则2
		if (_root->_color == RED)	return false;

		int refVal = 0;		// 参考值, 记录某一条路径上的黑色节点的数量
		Node* cur = _root;
		while (cur) {
			if (cur->_color == BLACK)
				refVal++;
			cur = cur->_left;
		}
		int blackNum = 0;

		return Check(_root, refVal, blackNum);
	}

	// 获得树的高度
	size_t GetHeight()
	{
		return _GetHeight(_root);
	}
	
	// 获得节点数
	size_t GetSize()
	{
		return _GetSize(_root);
	}
private:
	Node* _root = nullptr;
protected:
	// 新节点插入较高右子树的右侧---右右:左单旋  
	void RotateL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		// 由于parent不一定是整棵树的根,后面更新subR的parent时需要用到parentParent
		Node* parentParent = parent->_parent;

		parent->_right = subRL;
		// 注意,subRL可能为nullptr
		if (subRL)
			subRL->_parent = parent;
		subR->_left = parent;
		parent->_parent = subR;

		if (parent == _root) {
			_root = subR;
			subR->_parent = nullptr;
		}
		// parent不是整棵树的根
		else {
			if (parentParent->_left == parent)
				parentParent->_left = subR;
			else
				parentParent->_right = subR;
		}
		subR->_parent = parentParent;
	}

	// 新节点插入较高左子树的左侧---左左:右单旋  
	void RotateR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;
		Node* parentParent = parent->_parent;

		parent->_left = subLR;
		if (subLR)
			subLR->_parent = parent;
		subL->_right = parent;
		parent->_parent = subL;

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

	void _InOrder(Node* root)
	{
		if (root == nullptr)	return;
		_InOrder(root->_left);
		cout << root->_kv.first << ' ';
		_InOrder(root->_right);
	}

	bool Check(Node* root, const int& refVal, int blackNum)
	{

		if (root == nullptr) { 
			// cout << blackNum << endl;
			if(blackNum == refVal)
				return true; 
			else {
				cout << "有路径黑色节点数量不一致" << endl;
				return false;
			}
		}
		if (root->_color == BLACK)	blackNum++;
		if (root->_color == RED && root->_parent->_color == RED) {
			// 违反规则3
			cout << "有连续的红色节点" << endl;
			return false;
		}
		
		return Check(root->_left, refVal, blackNum) 
			&& Check(root->_right, refVal, blackNum);
	}

	size_t _GetHeight(Node* root)
	{
		if (root == nullptr)	return 0;
		size_t left = _GetHeight(root->_left);
		size_t right = _GetHeight(root->_right);
		return left > right ? left + 1 : right + 1;
	}
	size_t _GetSize(Node* root)
	{
		if (root == nullptr)	return 0;
		else return _GetSize(root->_left) + _GetSize(root->_right) + 1;
	}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值