0
点赞
收藏
分享

微信扫一扫

腾讯mini项目-【指标监控服务重构】2023-07-29

Sophia的玲珑阁 2023-09-16 阅读 6

文章目录


前言

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

一、红黑树的插入操作

1.红黑树结点的定义

enum Color {
	RED,
	BLACK
};
template<class K,class V>
struct RBTreeNode {
	RBTreeNode* _left;
	RBTreeNode* _right;
	RBTreeNode* _parent;
	pair<K, V>_kv;
	Color _col;//颜色

	RBTreeNode(const pair<K,V>&kv)
		:_left(nullptr),
		_right(nullptr),
		_parent(nullptr),
		_kv(kv),
		_col(RED)
		//结点默认给成红色是为了方便后续的插入
		//因为默认为黑色的话还需要考虑所有路径上黑色结点数量是否相同
		//太麻烦了
	{}
};

2.红黑树的插入

1.uncle存在且为红

这种情况就不需要考虑旋转了
在这里插入图片描述
在这里插入图片描述

2.uncle不存在

在这里插入图片描述

3.uncle存在且为黑

在这里插入图片描述
在这里插入图片描述

3.完整代码

template<class K,class V>
class RBTree {
	typedef RBTreeNode<K,V> Node;
public:
	bool Insert(const pair<K, V>& kv) {
		if (_root == nullptr) {
			//根节点必须为黑色
			_root = new Node(kv);
			_root->_col = BLACK;
			return true;
		}
		Node* cur = _root;
		Node* 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 = new Node(kv);
		cur->_col = RED;
		//插入对应位置,默认为红色
		if (parent->_kv.first < kv.first) {
			parent->_right = cur;
		}
		else {
			parent->_left = cur;
		}
		cur->_parent = parent;
		//让新插入结点指向父亲

		while (parent && parent->_col == RED) {
			Node* grandfather = parent->_parent;
			if (parent = grandfather->_left) {
				Node* uncle = grandfather->_right;
				if (uncle && uncle->_col == RED) {//uncle存在且为红
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					//继续向上更新
					cur = grandfather;
					parent = cur->_parent;
				}
				else {//uncle不存在或者uncle为黑
					if (cur == parent->_left) {
						//     g
						//   p
						// c
						RotateR(grandfather);
						grandfather->_col = RED;
						parent->_col = BLACK;
					}
					else {
						//     g
						//   p
						//		c
						RotateL(parent);
						RotateR(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;

					}
					break;
				}
			}
			else {// parent == grandfather->_right
				Node* uncle = grandfather->_right;
					if (uncle && uncle->_col == RED) {//uncle存在且为红
						parent->_col = uncle->_col = BLACK;
						grandfather->_col = RED;
						//继续向上更新
						cur = grandfather;
						parent = cur->_parent;

					}
					else {//uncle不存在或者uncle为黑
						if (cur == parent->_right) {
							// g
						   //	  p
						   //       c
							RotateL(grandfather);
							parent->_col = BLACK;
							grandfather->_col = RED;
						}
						else {
							// g
							//	  p
							// c
							RotateR(parent);
							RotateL(grandfather);
							cur->_col = BLACK;
							grandfather->_col = RED;
						}
						break;
					}
			}
		}
		_root->_col = BLACK;
			//根节点必须为黑色
		return true;
	}

	void RotateL(Node* parent) {//左旋
		Node* cur = parent->_right;
		Node* curleft = cur->_left;
		parent->_right = curleft;
		if (curleft) {
			curleft->_parent = parent;
		}
		cur->_left = parent;
		Node* ppnode = parent->_parent;
		if (ppnode == nullptr) {
			_root = cur;
			cur->_parent = nullptr;
		}
		else {
			if (ppnode->_left = parent) {
				ppnode->_left = cur;
			}
			else {
				ppnode->_right = cur;
			}
			cur->_parent = ppnode;
		}

	}

	void RotateR(Node* parent) {//右旋
		Node* cur = parent->_left;
		Node* curright = cur->_right;
		parent->_left = curright;
		if (curright) {
			curright->_parent = parent;
		}
		cur->_right = parent;
		Node* ppnode = parent->_parent;
		parent->_parent = cur;
		if (ppnode == nullptr) {
			_root = cur;
			cur->_parent = nullptr;
		}
		else {
			if (ppnode->_left == parent) {
				ppnode->_left = cur;
			}
			else {
				ppnode->_right = cur;
			}
			cur->_parent = ppnode;
		}
	}
};

二、是否为红黑树的验证

1.IsBlance函数

bool IsBalance() {
		return IsBalance(_root);
	}
	bool IsBalance(Node* root) {
		if (root == nullptr) {
			return true;
		}
		if (root->_col != BLACK) {
			return false;
		}//根节点一定为黑色
		int benchmark = 0;
		Node* cur = _root;
		while (cur) {//算出最左边黑色结点的数目,为了与
			//其他路径黑色结点的数目作比较
			if (cur->_col == BLACK) {
				benchmark++;
			}
			cur = cur->_left;
		}
		return CheckColor(root, 0, benchmark);
	}

2.CheckColor函数

bool CheckColor(Node* root, int blacknum, int benchmark) {
		if (root == nullptr) {
			//root为空说明已经数完了一条路径的黑色结点
			//与原先数的最左的黑色节点数进行比较
			if (blacknum != benchmark) {
				return false;
			}
			return true;
		}
		if (root->_col == BLACK) {
			blacknum++;//当前路径黑色结点树++
		}
		if (root->_col == RED && root->_parent && root->_parent->_col == RED) {
			cout << root->_kv.first << "出现连续红色节点" << endl;
			//判断是否出现连续的红色结点
			return false;
		}
		//递归式对左右子树分别检验
		return CheckColor(root->_left, blacknum, benchmark) && CheckColor(root->_right, blacknum, benchmark);
	}

三、红黑树与AVL树的比较

举报

相关推荐

0 条评论