手撕红黑树

目录

性质

插入规则

调整方法

插入在grandfather的左子树

uncle存在为红色(变色)

uncle不存在或存在为黑色(旋转+变色)

插入在grandfather的右子树

uncle存在且为红色(变色)

uncle不存在或者存在为黑色(旋转+变色)

整体分析

完整代码


性质

近似平衡的二叉搜索树

最长路径不超过最短路径的两倍

1.每个结点不是黑色就是黑色

2.根节点是黑色

3.不能出现连续的红色结点(连续结点组成:红+黑    黑+红   黑+黑)

4.每条路径的黑色结点数目相同

5.叶子节点都为黑色(空结点)NIL结点

分析:

最短路径:全黑

最长路径:黑红相间

每条路径的黑色节点数相同,所以最长路径最长是最短路径的两倍,不会超过

插入规则

插入黑色结点会影响整体,所以新节点插入红色结点

1.如果插入结点的父亲是黑色,不需要处理

2.如果插入结点的父亲是红色,那么需要进行处理(1.变色   2.旋转+变色)

需要处理下还分为两种情况

1.uncle存在为红色     变色

2.uncle不存在或存在为黑色      旋转+变色

调整方法

插入在grandfather的左子树

uncle存在为红色(变色)

只需要将p和u变为黑色,g变为红色,然后令c=g继续往上调整

1.插入在parent的左侧

手撕红黑树_第1张图片

2.插入在parent的右侧

手撕红黑树_第2张图片

uncle不存在或存在为黑色(旋转+变色)

插入在parent的左边

单纯变色无法完成调整,我们需要先进行右单旋再进行变色

1.uncle不存在

手撕红黑树_第3张图片

2.uncle存在且为黑

手撕红黑树_第4张图片

代码

手撕红黑树_第5张图片

插入在parent的右边

类别于AVL树,这里需要进行双旋再变色

1.uncle不存在

手撕红黑树_第6张图片

2.uncle存在且为黑

手撕红黑树_第7张图片

这种情况肯定是由这种情况变色而造成

(f的左子树里必含有一个黑色节点)

手撕红黑树_第8张图片

进行旋转

手撕红黑树_第9张图片

变色

手撕红黑树_第10张图片

代码

手撕红黑树_第11张图片

插入在grandfather的右子树

uncle存在且为红色(变色)

1.插入在parent的右边

手撕红黑树_第12张图片

2.插入在parent的左边‘’

手撕红黑树_第13张图片

代码

手撕红黑树_第14张图片

uncle不存在或者存在为黑色(旋转+变色)

插入在parent的右侧

1.uncle不存在

手撕红黑树_第15张图片

2.uncle存在且为黑色

手撕红黑树_第16张图片

代码

手撕红黑树_第17张图片

插入在parent的左侧

1.uncle不存在

手撕红黑树_第18张图片

2.uncle存在且为黑色

手撕红黑树_第19张图片

代码

手撕红黑树_第20张图片

整体分析

创建结点

手撕红黑树_第21张图片

插入

插入新节点是红色

插入分为两种情况

1.父节点为黑色不做处理

2.父节点为红色

又分为两种情况(见调整方法)

判断是否为红黑树

手撕红黑树_第22张图片

完整代码

#pragma once
enum Colour
{
	RED,
	BLACK
};

template
struct RBTreeNode
{
	RBTreeNode* _left;
	RBTreeNode* _parent;
	RBTreeNode* _right;
	pair _kv;
	Colour _col;

	RBTreeNode(const pair& kv)
		:_left(nullptr)
		,_parent(nullptr)
		,_right(nullptr)
		,_kv(kv)
		,_col(RED)
	{  }
};

template
class RBTree
{
	typedef RBTreeNode Node;
public:
	bool Insert(const pair& 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->_left;
			}
			else if (cur->_kv.first < kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return false;
			}
		}

		//插入
		cur = new Node(kv);
		if (parent->_kv.first > kv.first)
		{
			parent->_left = cur;
		}
		else
		{
			parent->_right = cur;
		}
		cur->_parent = parent;

		//调整
		//1.父亲为黑不需要调整
		//2.父亲为红需要调整
		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;
			//新增结点在左子树
			//      g
			//   p     u
			//   c
			if (parent == grandfather->_left)
			{
				//1.uncle存在且为红色
				Node* uncle = grandfather->_right;
				if (uncle && uncle->_col == RED)
				{
					//变色
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					//继续向上处理
					cur = grandfather;
					parent = cur->_parent;
				}
				//2.uncle不存在或uncle存在且为黑色
				//             g
				//         p
				//      c
				else
				{
					if (cur == parent->_left)
					{
						RotateR(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						//旋转
						RotateL(parent);
						RotateR(grandfather);
						//变色
						grandfather->_col = RED;
						cur->_col = BLACK;
					}
					break;
				}
			}
			else
			{
				//1.uncle存在且为红色
				Node* uncle = grandfather->_left;
				if (uncle && uncle->_col == RED)
				{
					//变色
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					//继续向上处理
					cur = grandfather;
					parent = cur->_parent;
				}
				//uncle不存在或者存在且为黑
				else
				{
					//插入在parent的右边
					if (cur == parent->_right)
					{
						RotateL(grandfather);
						grandfather->_col = RED;
						parent->_col = BLACK;
					}
					else
					{
						RotateR(parent);
						RotateL(grandfather);
						grandfather->_col = RED;
						cur->_col = BLACK;
					}
					break;
				}
			}
		}
		_root->_col = BLACK;
		return true;
	}

	void RotateR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		parent->_left = subLR;
		subL->_right = parent;

		Node* parentparent = parent->_parent;
		if (subLR)
			subLR->_parent = parent;
		parent->_parent = subL;

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

	void RotateL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;

		parent->_right = subRL;
		subR->_left = parent;

		Node* parentparent = parent->_parent;
		if (subRL)
			subRL->_parent = parent;
		parent->_parent = subR;

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

	bool IsBalance()
	{
		return _IsBalance(_root);
	}
	bool _IsBalance(Node* root)
	{
		if (root == nullptr)
		{
			return true;
		}

		if (root->_col != BLACK)
		{
			return false;
		}

		Node* cur = _root;
		int benmark = 0;
		while (cur)
		{
			if (cur->_col == BLACK)
			{
				++benmark;
			}
			cur = cur->_left;
		}
		return _IsValidRBTRee(_root, 0, benmark);
	}

	bool _IsValidRBTRee(Node* root, int blacknum, int benmark)
	{
		if (root == nullptr)
		{
			if (blacknum != benmark)
			{
				return false;
			}
			return true;
		}

		if (root->_col == BLACK)
		{
			++blacknum;
		}

		if (root->_col == RED && root->_parent->_col == RED)
		{
			cout << "连续红结点" << endl;
			return false;
		}

		return _IsValidRBTRee(root->_left, blacknum, benmark)
			&& _IsValidRBTRee(root->_right, blacknum, benmark);
	}

	int Size()
	{
		return _Size(_root);
	}

	int _Size(Node* root)
	{
		if (root == nullptr)
		{
			return 0;
		}

		return _Size(root->_left) + _Size(root->_right) + 1;
	}

	void Inorder()
	{
		_Inorder(_root);
		cout << endl;
	}

	void _Inorder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}

		_Inorder(root->_left);
		cout << root->_kv.first << ' ';
		_Inorder(root->_right);
	}

private:
	Node* _root = nullptr;
};

测试代码

手撕红黑树_第23张图片

你可能感兴趣的:(数据结构,数据结构,c++)