【C++】红黑树(Red Black Tree)

 什么是红黑树

从概念上来讲,它是一种二叉搜索树,但每一个节点不是红色就是黑色,它保证最长路径不会比其他路径长出两倍

为什么能保证,就要看下面几条性质:

1. 每个结点不是红色就是黑色
2. 根节点是黑色的
3. 如果一个节点是红色的,则它的两个孩子结点是黑色的
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点
5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

 

为什么满足了上面的性质就可以保证最长的不超过最短的两倍?

因为最短路径肯定是全黑,但是最长路径是黑红黑红,因为其保证了每条路径黑色节点数量要一致,所以最长的黑红最多也就等于两倍的黑

二叉树节点的定义

这里会跟AVL树有所不同,因为这里之后要复用到map,所以会稍作修改

首先为了区分颜色,我们就可以用到枚举:

enum Color
{
	Red,
	Black
};

然后创建节点的结构体,这里跟AVLTree差不多

template<class K,class V>
struct RBTreeNode
{
	pair<K, V> _kv;
	RBTreeNode<K, V>* _parent;
	RBTreeNode<K, V>* _left;
	RBTreeNode<K, V>* _right;

	Color _color;

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

};

顺便写一个构造函数,也很简单,把指针置为空,将里面的值用外面的拷贝一份,这里要注意的是,为什么插入节点的颜色要是红色。

这里我们插入节点是一定要给颜色的,给颜色就会出现两种情况:

3. 如果一个节点是红色的,则它的两个孩子结点是黑色的
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点

如果我们插入红色,有可能会违反3,因为它的父亲节点可能是红色的,但如果我们插入黑色节点,那就一定会违反4,因为你在一条支路里面插入黑色节点,如何确保其他路上的黑色节点数量一样就是个问题 

红黑树的插入

先简单写一个红黑树的大框架出来

template<class K, class V>
class RBTree
{
	typedef RBTreeNode<K, V> Node;



private:
	Node* _root = nullptr;
};

然后就可以考虑写插入了,这里需要提醒一下,是否还记得AVL树的旋转,这里红黑树也需要用到,如果不记得,这里放上另一篇博客的链接可供参考:

【C++】AVL_Knous的博客-CSDN博客

ok,最基本的先写上,如果这是一个空树,那最开始插入的就是根节点:


		//判断这是否为空树,是就直接插入
		if (_root == nullptr)
		{
			_root = new Node(kv);
			//根节点一定要是黑色
			_root->_color = Black;
			return true;
		}

然后,就可以开始插入了,插入部分根AVL基本一致

		Node* cur = _root;
		Node* parent = cur->_parent;
		while (cur)
		{
			if (cur->_kv.first > kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_kv.first < kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
				return false;

			cur = new Node(kv);
			cur->_color = Red;
			if (cur = parent->_left)
				parent->_left = cur;
			else
				parent->_right = cur;

然后就是我们需要处理的地方,我们就开始判断:

假设,我们在这个位置插入,肯定是没问题的࿰

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
是一种自平衡的二叉搜索,它具有以下特性: 1. 每个节点要么是色,要么是色。 2. 根节点是色的。 3. 每个叶子节点(NIL节点,空节点)是色的。 4. 如果一个节点是色的,则它的两个子节点都是色的。 5. 对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数目的色节点。 下面是一个简单的C++实现的代码示例: ```cpp #include <iostream> enum Color { RED, BLACK }; struct Node { int data; Color color; Node* left; Node* right; Node* parent; Node(int data) : data(data), color(RED), left(nullptr), right(nullptr), parent(nullptr) {} }; class RedBlackTree { private: Node* root; void rotateLeft(Node* node) { Node* rightChild = node->right; node->right = rightChild->left; if (rightChild->left != nullptr) { rightChild->left->parent = node; } rightChild->parent = node->parent; if (node->parent == nullptr) { root = rightChild; } else if (node == node->parent->left) { node->parent->left = rightChild; } else { node->parent->right = rightChild; } rightChild->left = node; node->parent = rightChild; } void rotateRight(Node* node) { Node* leftChild = node->left; node->left = leftChild->right; if (leftChild->right != nullptr) { leftChild->right->parent = node; } leftChild->parent = node->parent; if (node->parent == nullptr) { root = leftChild; } else if (node == node->parent->left) { node->parent->left = leftChild; } else { node->parent->right = leftChild; } leftChild->right = node; node->parent = leftChild; } void fixInsertion(Node* node) { while (node != root && node->parent->color == RED) { if (node->parent == node->parent->parent->left) { Node* uncle = node->parent->parent->right; if (uncle != nullptr && uncle->color == RED) { node->parent->color = BLACK; uncle->color = BLACK; node->parent->parent->color = RED; node = node->parent->parent; } else { if (node == node->parent->right) { node = node->parent; rotateLeft(node); } node->parent->color = BLACK; node->parent->parent->color = RED; rotateRight(node->parent->parent); } } else { Node* uncle = node->parent->parent->left; if (uncle != nullptr && uncle->color == RED) { node->parent->color = BLACK; uncle->color = BLACK; node->parent->parent->color = RED; node = node->parent->parent; } else { if (node == node->parent->left) { node = node->parent; rotateRight(node); } node->parent->color = BLACK; node->parent->parent->color = RED; rotateLeft(node->parent->parent); } } } root->color = BLACK; } public: RedBlackTree() : root(nullptr) {} void insert(int data) { Node* newNode = new Node(data); Node* current = root; Node* parent = nullptr; while (current != nullptr) { parent = current; if (data < current->data) { current = current->left; } else { current = current->right; } } newNode->parent = parent; if (parent == nullptr) { root = newNode; } else if (data < parent->data) { parent->left = newNode; } else { parent->right = newNode; } fixInsertion(newNode); } void printInorder(Node* node) { if (node == nullptr) { return; } printInorder(node->left); std::cout << node->data << " "; printInorder(node->right); } void printTree() { printInorder(root); } }; int main() { RedBlackTree tree; tree.insert(7); tree.insert(3); tree.insert(18); tree.insert(10); tree.insert(22); tree.insert(8); tree.insert(11); tree.insert(26); tree.insert(2); tree.insert(6); tree.insert(13); std::cout << "中序遍历结果:" << std::endl; tree.printTree(); return 0; } ``` 这段代码实现了的插入操作,并提供了一个简单的测试例子。你可以根据需要进行修改和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值