红黑树的模拟实现

一、红黑树名字的由来

首先要知道的就是红黑树名字的由来,像AVL树的由来是以发明它的大佬的名字命名的,红黑树的命名是它的结点不是红色就是黑色,因此以红黑树进行命名。先进行声明一点就是红黑树并不一定是一棵平衡树,最优的平衡树是AVL树,红黑树是通过颜色来控制这棵搜索树相对平衡的。

二、实现红黑树的规则

红黑树的实现规则:

  • 第一条:每一个结点不是红色就是黑色。
  • 第二条:根结点是黑色的。
  • 第三条:如果一个结点是红色那么它的孩子一定是黑色,也就是说每一条路径上都不可能有连续的红色结点
  • 第四条:对于任意一个结点,由该结点到其所有的简单路径上的黑色结点的数目都相同。

在这样的四条规则下会出现一个情况就是:最长路径不会超过最短路径的二倍。

下面需要证明的是为什么会出现这种情况呢?

其实很简单,就是每条路径都不可能出现连续的红色结点,这意味着,如果该路径存在红色结点,则该结点要么是叶子结点,要么是有两个黑色结点。这也表明,最长的路径一定是一黑一红交替出现。最短路径一定是全黑的。由于存在上面四条规则的束缚,这个结论一定是成立的。

不要说在黑色结点后面一直加黑色结点这种没有逻辑的话。第四条规则确保了每条路径上都有相同数量的黑色结点,这就不可能使得任意一条路径上的黑色结点无限多。

三、红黑树模拟实现

3.1、红黑树的效率分析

这两棵树都满足红黑树的规则,它们分别是两个极端,左边这棵树是只有黑色结点的一棵红黑树,他的结点数量一定是最少的满二叉树,而右边这棵树是结点数量最多的满二叉树。

也就是说,我们所有的红黑的结点数量都会介于这两种极端的二叉树之间,我们假设左边这棵树的高度为h那么右边这棵树的高度就为2 * h。也就是所结点数量为2^h - 1 <= N <= 2^2h - 1;也就是说这两种二叉树的效率都是O(logn)的。 这也是我们说的,虽然红黑树不和AVL树一样追求完全的平衡,但是它的效率依然很高。

3.2、模拟实现

3.2.1第一种情况:只进行变色处理即可达到平衡

分析一下这种情况,搜先再插入x结点指点,这棵树是满足红黑树的规则的也就是说在插入x结点之前这棵树是红黑树。插入了x结点后发现这棵树出现了红色结点相连的情况,这就不满足红黑树的规则了。需要进行调整。下面是调整的规则:

将先插入的结点定义为cur,分别找到他的parent,uncle,grandfather,然后进行下面的操作:即先判断parent是否为黑,如果为黑,就不用修改直接结束,如果为红,那就可以确定他一定有爷爷,并且爷爷一定为黑接下来就只是需要判断叔叔了。对于叔叔存在这样的三种情况,这三种情况的处理方式也是不一样的,第一种,叔叔存在且为红(就是图中这种)第二种叔叔存在且为黑,第三种,叔叔不存在。我们先来说图中这种的处理方法,就是将parent和uncle变黑,grandfather变红然后继续向上进行我们这种操作,直到cur不存在爷爷为止。我们发现他就满足我们红黑树的要求了,在这个过程中还会遇到其他的几种情况,下面我们来分开讲解。

if (uncle && uncle->_col == RED)
{
				parent->_col = uncle->_col = BLACK;
				grandfather->_col = RED;

				cur = grandfather;
				parent = cur->_parent;
}

对于uncle存在且为黑的情况是这样的:uncle存在且为黑这种情况,c一定是由下面子树的爷爷变化来的,也就说uncle存在且为黑这种情况一定是经历了一次第一种情况。

反证法:如果c是新插入的结点的话,那么每一条路径上都有相同的黑色结点这一条规则就不满足,所以c不可能是新插入的结点。

RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;				

3.3.3、进行双旋的情况

uncle不存在:

uncle存在且为黑:

RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;

四、模拟实现的代码

#pragma once
#include<iostream>
#include<utility>
using namespace std;

namespace Code_Journey
{
	enum color
	{
		RED,
		BLACK
	};
	template<class K, class V>
	struct RBTreeNode
	{
		RBTreeNode<K, V>* _left;
		RBTreeNode<K, V>* _right;
		RBTreeNode<K, V>* _parent;
		pair<K, V> _kv;
		color _col;

		RBTreeNode(const pair<K, V>& kv)
			:_left(nullptr)
			, _right(nullptr)
			, _parent(nullptr)
			, _kv(kv)
			, _col(RED)
		{
		}
	};
	template<class K, class V>
	class RBTree
	{
		typedef RBTreeNode<K, V> Node;
	public:
		bool insert(const pair<K, V>& kv)
		{
			// 1.插入结点
			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->_left;
				}
				else if (cur->_kv.first < kv.first)
				{
					parent = cur;
					cur = cur->_right;
				}
				else
				{
					return false;
				}
			}
			cur = new Node(kv);

			if (cur->_kv.first < parent->_kv.first) parent->_left = cur;
			else parent->_right = cur;
			// 更新cur结点的_parent成员
			cur->_parent = parent;
			cur->_col = RED;
			// 如果parent存在并且颜色为红色就一定是需要进行处理的
			// 第一就是parent存在且为红他就一定有爷爷,这个在分析
			// 原理的时候说过了,这种需要进行更新的情况就只有uncle
			// 是变化的。
			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;

						cur = grandfather;
						parent = cur->_parent;
					}
					else if (uncle == nullptr || uncle->_col == BLACK)
					{
						if (cur == parent->_left)
						{
							RotateR(grandfather);
							parent->_col = BLACK;
							grandfather->_col = RED;
						}
						else
						{
							RotateL(parent);
							RotateR(grandfather);
							cur->_col = BLACK;
							grandfather->_col = RED;
						}
						break;
					}
				}
				else
				{
					Node* uncle = grandfather->_left;
					if (uncle && uncle->_col == RED)
					{
						parent->_col = uncle->_col = BLACK;
						grandfather->_col = RED;

						cur = grandfather;
						parent = cur->_parent;
					}
					else if (uncle == nullptr || uncle->_col == BLACK)
					{
						if (cur == parent->_right)
						{
							RotateL(grandfather);
							parent->_col = BLACK;
							grandfather->_col = RED;
						}
						else
						{
							RotateR(parent);
							RotateL(grandfather);
							cur->_col = BLACK;
							grandfather->_col = RED;
						}
						break;
					}
				}
			}
			_root->_col = BLACK;
			return true;
		}
		bool IsBalanceTree()
		{
			int ref = _BlackNodeNums(_root, 0);
			// cout << ref << endl;
			return  _IsBalanceTree(_root, 0, ref);
		}
		void InOrder()
		{
			inorder(_root);
			cout << endl;
		}
		int Height()
		{
			return _Height(_root);
		}
		Node* find(const K& key)
		{
			if (_root == nullptr)
			{
				return nullptr;
			}
			Node* cur = _root;
			while (cur)
			{
				if (cur->_kv.first > key)
				{
					cur = cur->_left;
				}
				else if (cur->_kv.first < key)
				{
					cur = cur->_right;
				}
				else
				{
					return cur;
				}
			}
			return nullptr;
		}
		size_t Size()
		{
			return size(_root);
		}
	private:
		void RotateR(Node* parent)
		{
			Node* subL = parent->_left;
			Node* subLR = subL->_right;
			Node* ppnode = parent->_parent;

			// 更新b子树
			parent->_left = subLR;
			if (subLR)
				subLR->_parent = parent;

			// 更新parent
			subL->_right = parent;
			parent->_parent = subL;
			// 判断ppnode是否为空
			if (parent == _root)
			{
				_root = subL;
				subL->_parent = nullptr;
			}
			else
			{
				if (ppnode->_left == parent)
				{
					ppnode->_left = subL;
				}
				else
				{
					ppnode->_right = subL;
				}
				subL->_parent = ppnode;
			}
		}
		void RotateL(Node* parent)
		{
			Node* subR = parent->_right;
			Node* subRL = subR->_left;
			Node* ppnode = parent->_parent;

			// 更新b子树
			parent->_right = subRL;
			if (subRL)
				subRL->_parent = parent;

			// 更新parent
			subR->_left = parent;
			parent->_parent = subR;
			// 判断ppnode是否为根结点
			if (parent == _root)
			{
				_root = subR;
				subR->_parent = nullptr;
			}
			else
			{
				if (ppnode->_left == parent)
				{
					ppnode->_left = subR;
				}
				else
				{
					ppnode->_right = subR;
				}
				subR->_parent = ppnode;
			}
		}
		size_t size(Node* root)
		{
			if (root == nullptr)
			{
				return 0;
			}
			return size(root->_left) + size(root->_right) + 1;
		}
		int _Height(Node* root)
		{
			if (root == nullptr)
				return 0;
			int leftHeight = _Height(root->_left);
			int rightHeight = _Height(root->_right);
			return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
		}
		bool _IsBalanceTree(Node* root, int size, int ref)
		{
			if (nullptr == root)
				return true;
			if (_root->_col == RED)
				return false;
			return _check(root, size, ref);
		}
		bool _check(Node* root, int size, int ref)
		{
			if (root == nullptr)
			{
				// 写到里面解决的就是空指针解引用的问题
				if (size != ref)
				{
					return false;
				}
				return true;
			}
			if (root->_col == BLACK) size++;
			if (root->_col == RED && root->_parent->_col == RED)
			{
				return false;
			}
			else
			{
				return true;
			}
			return _check(root->_left, size, ref) && _check(root->_right, size, ref);
		}
		
		int _BlackNodeNums(Node* root, int size)
		{
			if (root == nullptr)
			{
				return size;
			}
			if (root->_col == BLACK)
			{
				size++;
			}
			return _BlackNodeNums(root->_left, size);
		}
		void inorder(Node* root)
		{
			if (root == nullptr)
			{
				return;
			}
			inorder(root->_left);
			cout << root->_kv.first << ' ';
			inorder(root->_right);
		}
	private:
		Node* _root = nullptr;
	};
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值