当前位置: 首页 > article >正文

红黑树1.0

 1.红黑树的概念

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

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

3.插入情况分类

code:(待完善)

#pragma once
#include<iostream>
using namespace std;
#include<assert.h>
#include<vector>
#include <cstdlib>
#include <ctime>
//红黑树的规则
//1.每个节点不是黑色就是红色
//2.根节一定是黑色
//3.一个节点是红色,则它的子节点一定都是黑色
//4.对于每个节点,从该节点到它的后代的简单路径上,它们的黑色节点的个数一定相同
//5.每个叶子节点都是黑色,此处叶子节点指的是空节点

//枚举
enum colour
{
	RED,
	BLACK
};

template<class K,class V>
struct RBnode
{
	pair<K, V> _kv;
	colour _con;
	RBnode<K, V>* _parent;
	RBnode<K, V>* _left;
	RBnode<K, V>* _right;
	RBnode(const pair<K, V>& kv):_kv(kv),_con(RED), _parent(nullptr), _left(nullptr), _right(nullptr) {}
};

template<class K,class V>
class RBtree
{
	typedef RBnode<K, V> node;
public:
	RBtree():_root(nullptr) {};
	bool _insert(const pair<K, V>& kv)//引用单纯是为了避免拷贝构造的开销
	{
		try
		{
			cout << "1111" << " ";
			if (_root == nullptr)
			{
				_root= new node(kv);
				_root->_con = BLACK;
				return true;
			}
			node* cur = _root;
			node* parent = nullptr;
			while (cur)
			{
				parent = cur;
				if (cur->_kv.first > kv.first)
				{
					cur = cur->_left;
				}
				else if (cur->_kv.first < kv.first)
				{
					cur = cur->_right;
				}
				else
				{
					return false;
				}
			}

			cur = new node(kv);
			cur->_con = RED;
			cur->_parent = parent;
			(parent->_kv.first > cur->_kv.first) ? (parent->_left = cur) : (parent->_right = cur);
			//红黑树调整代码
			while (parent&&parent->_con==RED)
			{
				node* grandFather = parent->_parent;
				if (parent==grandFather->_left)
				{
					node* uncle = parent->_right;
					//规则一:uncle存在且为红色,把parent和uncle变色为黑色,然后gf变为黑色,向上调整
					if (uncle&&uncle->_con==RED)
					{
						parent->_con = BLACK;
						uncle->_con = BLACK;
						grandFather->_con = RED;

						//继续向上调整
						cur = grandFather;
						parent = cur->_parent;
					}
					else//情况二
					{
						if (cur == parent->_left)
						{
							//    g
							//  p
							//c
							//cur在父亲的左
							RotateR(grandFather);
							parent->_con = BLACK;
							grandFather->_con = RED;
						}
						else
						{
							//     g
							//   p
							//     c
							RotateL(parent);
							RotateR(grandFather);
							cur->_con = BLACK;
							grandFather->_con = RED;
						}
					}
				}
				else if (parent == grandFather->_right)
				{
					node* uncle = grandFather->_left;
					if (uncle && uncle->_con == RED)
					{
						parent->_con = BLACK;
						uncle->_con = BLACK;
						grandFather->_con = RED;

						//继续向上调整
						cur = grandFather;
						parent = cur->_parent;
					}
					else
					{
						if (cur == parent->_right)
						{
							RotateL(grandFather);
							parent->_con = BLACK;
							grandFather->_con = RED;

							/
							//cur = parent;             // 关键修复:cur 指向新的父节点
							//parent = cur->_parent;    // parent 更新为 cur 的父节点

						}
						else
						{
							//      g
							//   u     p
							//       c
							RotateR(parent);
							RotateL(grandFather);
							cur->_con = BLACK;
							grandFather->_con = RED;

							
							/*parent = cur->_parent; */    // parent 指向 cur 的新父节点
						}
						break;
					}
				}
				
			}
			_root->_con = BLACK;//不管最后结果如何一定要确保根节点为黑色

		}
		catch (const std::exception&e)
		{
			cout << "抛异常:" << " ";
			cout << e.what() << endl;
		}
		

		return true;
	}
	void inorder()
	{
		cout << "中序遍历:" << " ";
		_inorder(_root);
	}
	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;

	}
	size_t size()
	{
		return _size(_root);
	}

	int height()
	{
		return _Height(_root);
	}
	size_t _size(node* root)
	{
		if (root == nullptr)
			return 0;
		return _size(root->_left) + _size(root->_right) + 1;
	}

	bool check(node* root,int blacknum,const int rev)
	{
		if (root == nullptr)
		{
			if (rev != blacknum)
			{
				cout << "存在黑色节点数量不相等!" << endl;
				return false;
			}
			return true;
		}

		if (root->_con == RED && root->_parent->_con == RED)
		{
			//这里很巧妙的处理连续红色检查,因为儿子有两个、
			// ,但是父亲只有一个检查父亲和root然后进行一个递归就可以查出所有的连续红色
			cout << "出现连续的红色" << endl;

			return false;
		}
		if (root->_con == BLACK)
		{
			++blacknum;
		}

		return check(root->_left,blacknum,rev) && check(root->_right,blacknum,rev);
	}

	bool isbalance()
	{
		if (_root == nullptr)
			return true;
		if (_root->_con == RED)
		{
			return false;
		}

		int rev = 0;
		node* cur = _root;
		if (cur->_con == BLACK)
		{
			++rev;
		}

		int blacknum = 0;
		return check(_root,blacknum,rev);
	}

private:
	void _inorder(node* root)
	{
		if (root == nullptr)
			return;
		_inorder(root->_left);
		cout << root->_kv.first << " ";
		_inorder(root->_right);
	}
	void RotateL(node* parent)
	{

		node* p_parent = parent->_parent;
		node* subR = parent->_right;
		node* subRL = subR->_right;
		parent->_right = subRL;
		subR->_left = parent;
		parent->_parent = subR;
		if (subRL)
			subRL->_parent = parent;
		if (_root == parent)
		{
			_root = subR;
			subR->_parent = nullptr;
		}
		else
		{
			if (p_parent->_left == parent)//记住因为此时原树并没有被摧毁,parent节点也还没有更新,并不是说树的指针只能有两个指向
			{
				p_parent->_left = subR;
			}
			else if(p_parent->_right==parent)
			{
				p_parent->_right = subR;
			}
			subR->_parent = p_parent;
		}

	}

	void RotateR(node* parent)
	{
		if (parent == nullptr) return;
		node* subL = parent->_left;
		node* subLR = subL->_right;
		node* p_parent = parent->_parent;
		subL->_right = parent;
		parent->_left = subLR;
		if (subLR)
		{
			subLR->_parent = parent;
		}
		if (_root == parent)
		{
			_root = subL;
			subL->_parent = nullptr;
		}
		else
		{
			if (p_parent->_left == parent)
			{
				p_parent->_left = subL;
			}
			else if (p_parent->_right == parent)
			{
				p_parent->_right = subL;
			}
			else
			{
				assert(false);
			}
			subL->_parent = p_parent;
		}
	}
	node* _root=nullptr;
};


http://www.kler.cn/a/597734.html

相关文章:

  • MongoDB未授权访问漏洞
  • Go红队开发—CLI框架(一)
  • IDEA修改默认作者名称
  • 【杂记二】git, github, vscode等
  • Rust嵌入式开发环境搭建指南(基于Stm32+Vscode)
  • Dervy数据库
  • 实验11 机器学习-贝叶斯分类器
  • OpenCV旋转估计(5)图像拼接的一个函数waveCorrect()
  • 集群环境下Redis 商品库存系统设计
  • 深入解析 Java Stream API:从 List 到 Map 的优雅转换!!!
  • ffmpeg库视频硬编码使用流程
  • 如何为在线游戏选择合适的游戏盾?
  • 互相关-信号增强
  • Verilog学习之TASK的使用
  • 【linux】scp和rsync
  • 深度学习-151-Dify工具之创建一个生成财务报表的智能体Agent
  • 使用bat批量获取WORD中包含对应字符的段落,段落使用回车换行
  • CEFPN
  • for循环 jdk8 stream Api写法
  • 爬虫逆向解决debugger问题