【C++ RB树】

红黑树

AVL树是一颗绝对平衡的二叉搜索树,要求每个节点的左右高度差的绝对值不超过1,这样保证查询时的高效时间复杂度O( l o g 2 N ) log_2 N) log2N),但是要维护其绝对平衡,旋转的次数比较多。因此,如果一颗树的结构经常修改,那么AVL树就不太合适,所以就有了红黑树。

红黑树的概念

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

红黑树的性质

  1. 每个节点不是红色就是黑色
  2. 根节点是黑色的
  3. 不存在连续的红色节点
  4. 任意一条从根到叶子的路径上的黑色节点的数量相同
    根据上面的性质,红黑树就可以确保没有一条路径会比其他路径长出两倍,因为每条路径上的黑色节点的数量相同,所以理论上最短边一定都是黑色节点,最长边一定是一黑一红的不断重复的路径。

红黑树节点的定义

	enum Color
	{
		RED,
		BLACK
	};
	template<class K, class V>
	struct RBTreeNode
	{
		RBTreeNode<K, V>* _left;
		RBTreeNode<K, V>* _right;
		RBTreeNode<K, V>* _parent;
		Color _col;
		pair<K, V> _kv;
		RBTreeNode(const pair<K, V>& kv)
			:_left(nullptr)
			,_right(nullptr)
			,_parent(nullptr)
			,_col(RED)
			,_kv(kv)
		{}
	};

插入新节点的颜色一定是红色,因为如果新节点的颜色是黑色,那么每条路径上的黑色节点的数量就不相同了,处理起来就比较麻烦,所以宁愿出现连续的红色节点,也不能让某一条路径上多出一个黑色节点。

红黑树的插入

1.根据二叉搜索树的规则插入新节点

bool Insert(const pair<K, V>& kv)
{
	if (_root == nullptr)
	{
		_root = new Node(kv);
		_root->_col = BLACK;
		return true;
	}
	Node* curr = _root;
	Node* parent = nullptr;
	while (curr)
	{
		if (curr->_kv.first < kv.first)
		{
			parent = curr;
			curr = curr->_right;
		}
		else if (curr->_kv.first > kv.first)
		{
			parent = curr;
			curr = curr->_left;
		}
		else
		{
			return false;
		}
	}
	curr = new Node(kv);
	if (parent->_kv.first < kv.first)
		parent->_right = curr;
	else
		parent->_left = curr;
	curr->_parent = parent;
........

2.测新节点插入后,红黑树的性质是否造到破坏

bool Insert(const pair<K, V>& kv)
{
	if (_root == nullptr)
	{
		_root = new Node(kv);
		_root->_col = BLACK;
		return true;
	}
	Node* curr = _root;
	Node* parent = nullptr;
	while (curr)
	{
		if (curr->_kv.first < kv.first)
		{
			parent = curr;
			curr = curr->_right;
		}
		else if (curr->_kv.first > kv.first)
		{
			parent = curr;
			curr = curr->_left;
		}
		else
		{
			return false;
		}
	}
	curr = new Node(kv);
	if (parent->_kv.first < kv.first)
		parent->_right = curr;
	else
		parent->_left = curr;
	curr->_parent = parent;

	while (parent && parent->_col == RED)
	{
		Node* grandfather = parent->_parent;
		if (parent == grandfather->_left)
		{
			Node* uncle = grandfather->_right;
			if (uncle && uncle->_col == RED)
			{
				parent->_col = uncle->_col = BLACK;
				grandfather->_col = RED;

				curr = grandfather;
				parent = curr->_parent;
			}
			else
			{
				if (curr == parent->_left)
				{
					//      g
					//   p     u
					//c
					RotatoR(grandfather);
					parent->_col = BLACK;
					grandfather->_col = RED;
				}
				else
				{
					//      g
					//   p     u
					//    c
					RotatoL(parent);
					RotatoR(grandfather);
					curr->_col = BLACK;
					grandfather->_col = RED;
				}
				break;
			}
		}
		else
		{
			Node* uncle = grandfather->_left;
			if (uncle && uncle->_col == RED)
			{
				parent->_col = uncle->_col = BLACK;
				grandfather->_col = RED;

				curr = grandfather;
				parent = curr->_parent;
			}
			else
			{
				if (curr == parent->_right)
				{
					//      g   
					//   u     p
					//           c
					RotatoL(grandfather);
					parent->_col = BLACK;
					grandfather->_col = RED;
				}
				else
				{
					//      g   
					//   u     p
					//        c
					RotatoR(parent);
					RotatoL(grandfather);
					curr->_col = BLACK;
					grandfather->_col = RED;
				}
				break;
			}
		}
		
	}
	_root->_col = BLACK;
	return true;
}
void RotatoL(Node* parent)
{
	Node* subR = parent->_right;
	Node* subRL = subR->_left;
	parent->_right = subRL;
	if (subRL)
		subRL->_parent = parent;
	subR->_left = parent;
	Node* ppnode = parent->_parent;
	parent->_parent = subR;
	if (parent == _root)
	{
		_root = subR;
		subR->_parent = nullptr;
	}
	else
	{
		if (ppnode->_left == parent)
			ppnode->_left = subR;
		else
			ppnode->_right = subR;
		subR->_parent = ppnode;
	}
}
void RotatoR(Node* parent)
{
	Node* subL = parent->_left;
	Node* subLR = subL->_right;
	parent->_left = subLR;
	if (subLR)
		subLR->_parent = parent;
	subL->_right = parent;
	Node* ppnode = parent->_parent;
	parent->_parent = subL;
	if (parent == _root)
	{
		_root = subL;
		subL->_parent = nullptr;
	}
	else
	{
		if (ppnode->_left == parent)
			ppnode->_left = subL;
		else
			ppnode->_right = subL;
		subL->_parent = ppnode;
	}
}

代码实现

#pragma once
#include <utility>

namespace lw
{
	enum Color
	{
		RED,
		BLACK
	};
	template<class K, class V>
	struct RBTreeNode
	{
		RBTreeNode<K, V>* _left;
		RBTreeNode<K, V>* _right;
		RBTreeNode<K, V>* _parent;
		Color _col;
		pair<K, V> _kv;
		RBTreeNode(const pair<K, V>& kv)
			:_left(nullptr)
			,_right(nullptr)
			,_parent(nullptr)
			,_col(RED)
			,_kv(kv)
		{}
	};
	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* curr = _root;
			Node* parent = nullptr;
			while (curr)
			{
				if (curr->_kv.first < kv.first)
				{
					parent = curr;
					curr = curr->_right;
				}
				else if (curr->_kv.first > kv.first)
				{
					parent = curr;
					curr = curr->_left;
				}
				else
				{
					return false;
				}
			}
			curr = new Node(kv);
			if (parent->_kv.first < kv.first)
				parent->_right = curr;
			else
				parent->_left = curr;
			curr->_parent = parent;

			while (parent && parent->_col == RED)
			{
				Node* grandfather = parent->_parent;
				if (parent == grandfather->_left)
				{
					Node* uncle = grandfather->_right;
					if (uncle && uncle->_col == RED)
					{
						parent->_col = uncle->_col = BLACK;
						grandfather->_col = RED;

						curr = grandfather;
						parent = curr->_parent;
					}
					else
					{
						if (curr == parent->_left)
						{
							//      g
							//   p     u
							//c
							RotatoR(grandfather);
							parent->_col = BLACK;
							grandfather->_col = RED;
						}
						else
						{
							//      g
							//   p     u
							//    c
							RotatoL(parent);
							RotatoR(grandfather);
							curr->_col = BLACK;
							grandfather->_col = RED;
						}
						break;
					}
				}
				else
				{
					Node* uncle = grandfather->_left;
					if (uncle && uncle->_col == RED)
					{
						parent->_col = uncle->_col = BLACK;
						grandfather->_col = RED;

						curr = grandfather;
						parent = curr->_parent;
					}
					else
					{
						if (curr == parent->_right)
						{
							//      g   
							//   u     p
							//           c
							RotatoL(grandfather);
							parent->_col = BLACK;
							grandfather->_col = RED;
						}
						else
						{
							//      g   
							//   u     p
							//        c
							RotatoR(parent);
							RotatoL(grandfather);
							curr->_col = BLACK;
							grandfather->_col = RED;
						}
						break;
					}
				}
				
			}
			_root->_col = BLACK;
			return true;
		}
		void RotatoL(Node* parent)
		{
			Node* subR = parent->_right;
			Node* subRL = subR->_left;
			parent->_right = subRL;
			if (subRL)
				subRL->_parent = parent;
			subR->_left = parent;
			Node* ppnode = parent->_parent;
			parent->_parent = subR;
			if (parent == _root)
			{
				_root = subR;
				subR->_parent = nullptr;
			}
			else
			{
				if (ppnode->_left == parent)
					ppnode->_left = subR;
				else
					ppnode->_right = subR;
				subR->_parent = ppnode;
			}
		}
		void RotatoR(Node* parent)
		{
			Node* subL = parent->_left;
			Node* subLR = subL->_right;
			parent->_left = subLR;
			if (subLR)
				subLR->_parent = parent;
			subL->_right = parent;
			Node* ppnode = parent->_parent;
			parent->_parent = subL;
			if (parent == _root)
			{
				_root = subL;
				subL->_parent = nullptr;
			}
			else
			{
				if (ppnode->_left == parent)
					ppnode->_left = subL;
				else
					ppnode->_right = subL;
				subL->_parent = ppnode;
			}
		}
		void InOrder()
		{
			_InOrder(_root);
		}
		bool IsBalance()
		{
			if (_root && _root->_col == RED)
				return false;
			Node* left = _root;
			int count = 0;
			while (left)
			{
				if (left->_col == BLACK)
					count++;
				left = left->_left;
			}
			return check(_root, 0, count);
		}
	private:
		bool check(Node* root, int count, int refBlackNumber)
		{
			if (root == nullptr)
			{
				if (count == refBlackNumber)
					return true;
				else
					return false;
			}
			if (root->_col == RED && root->_parent->_col == RED)
				return false;
			if (root->_col == BLACK)
				count++;
			return check(root->_left, count, refBlackNumber)
				&& check(root->_right, count, refBlackNumber);
		}
		void _InOrder(Node* root)
		{
			if (root == nullptr)
				return;
			_InOrder(root->_left);
			cout << root->_kv.first << " : " << root->_kv.second << endl;
			_InOrder(root->_right);
		}
		Node* _root = nullptr;
	};
}

总结

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

  • 22
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是C语言实现的红黑树代码: ```c #include <stdio.h> #include <stdlib.h> typedef struct Node { int key; int color; // 0表示黑色,1表示红色 struct Node *left, *right, *parent; } Node; typedef struct { Node *root; } RBTree; // 创建一个节点 Node *new_node(int key, int color) { Node *p = (Node*) malloc(sizeof(Node)); p->key = key; p->color = color; p->left = p->right = p->parent = NULL; return p; } // 左旋 void left_rotate(RBTree *T, Node *x) { Node *y = x->right; x->right = y->left; if (y->left != NULL) y->left->parent = x; y->parent = x->parent; if (x->parent == NULL) T->root = y; else if (x == x->parent->left) x->parent->left = y; else x->parent->right = y; y->left = x; x->parent = y; } // 右旋 void right_rotate(RBTree *T, Node *x) { Node *y = x->left; x->left = y->right; if (y->right != NULL) y->right->parent = x; y->parent = x->parent; if (x->parent == NULL) T->root = y; else if (x == x->parent->left) x->parent->left = y; else x->parent->right = y; y->right = x; x->parent = y; } // 插入一个节点 void rb_insert(RBTree *T, int key) { Node *z = new_node(key, 1); Node *y = NULL; Node *x = T->root; while (x != NULL) { y = x; if (z->key < x->key) x = x->left; else x = x->right; } z->parent = y; if (y == NULL) T->root = z; else if (z->key < y->key) y->left = z; else y->right = z; while (z != T->root && z->parent->color == 1) { if (z->parent == z->parent->parent->left) { Node *y = z->parent->parent->right; if (y != NULL && y->color == 1) { z->parent->color = 0; y->color = 0; z->parent->parent->color = 1; z = z->parent->parent; } else { if (z == z->parent->right) { z = z->parent; left_rotate(T, z); } z->parent->color = 0; z->parent->parent->color = 1; right_rotate(T, z->parent->parent); } } else { Node *y = z->parent->parent->left; if (y != NULL && y->color == 1) { z->parent->color = 0; y->color = 0; z->parent->parent->color = 1; z = z->parent->parent; } else { if (z == z->parent->left) { z = z->parent; right_rotate(T, z); } z->parent->color = 0; z->parent->parent->color = 1; left_rotate(T, z->parent->parent); } } } T->root->color = 0; } // 中序遍历 void inorder_traversal(Node *x) { if (x != NULL) { inorder_traversal(x->left); printf("%d ", x->key); inorder_traversal(x->right); } } // 主函数 int main() { RBTree T; T.root = NULL; rb_insert(&T, 10); rb_insert(&T, 20); rb_insert(&T, 30); rb_insert(&T, 100); rb_insert(&T, 50); rb_insert(&T, 60); rb_insert(&T, 70); inorder_traversal(T.root); return 0; } ``` 在这个例子中,我们实现了红黑树的插入操作,并对它进行了中序遍历。输出结果为: ``` 10 20 30 50 60 70 100 ``` 这证明了我们成功地将所有节点按照升序排列并插入了红黑树中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

LRBORRR

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

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

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

打赏作者

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

抵扣说明:

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

余额充值