红黑树的创建与介绍!!!(C++)

红黑树:
1.空树(红黑树可以是空树)
2.非空:二叉搜索树 + 给节点增加颜色(红色和黑色)

红黑树通过其性质的限制可以保证最长节点数不超过最短节点数的2倍

红黑树的性质
1.红黑树中的每个节点都有颜色,不是红色就是黑色
2.根节点的颜色必须是黑色
3.红色节点的孩子节点必须是黑色节点(不能有两个连续的红色节点)
4.每条路径的黑色节点数必须相等
5.所有“叶子节点”的颜色必须是黑色(可忽略)

注:
在这里插入图片描述
本红黑树是模拟实现STL底层的红黑树
在这里插入图片描述
在创建红黑树是我们先来看三种特殊的情况
在这里插入图片描述

在这里插入图片描述在这里插入图片描述
上面是插入到左子树时的节点的情况,如果插入到右子树,则是上述三种情况的反情况

#pragma once
#include <iostream>

using namespace std;

enum Color{RED, BLACK};

template<class T>
struct RBNode
{
	RBNode(const T& data = T(), Color c = RED)
		:val_(data)
		,color_(c)
		,parent_(nullptr)
		,left_(nullptr)
		,right_(nullptr)
	{}

	T val_;
	Color color_;
	struct RBNode* parent_;
	struct RBNode* left_;
	struct RBNode* right_;
};

template<class T>
class RBTree
{
	typedef RBNode<T> Node;
public:
	RBTree()
	{
		//创建空树(红黑树可以是空树)
		head = new Node();
		head->left_ = head;
		head->right_ = head;
	}

	~RBTree()
	{
		Destory(head->parent_);
	}

	void InOrder()
	{
		_InOrder(head->parent_);
		cout << endl;
	}

	bool Insert(const T& data)
	{
		//1.按二叉搜索树插入节点
		Node*& root = GetRoot();

		if (nullptr == root)
		{
			root = new Node(data, BLACK);
			root->parent_ = head;
			head->left_ = root;
			head->right_ = root;
			return true;
		}

		Node* cur = root;
		Node* parent = head;
		//找到要插入节点的位置
		while (cur)
		{
			parent = cur;
			if (data > cur->val_)
				cur = cur->right_;
			else if (data < cur->val_)
				cur = cur->left_;
			else
				return false;
		}

		cur = new Node(data);
		if (data > parent->val_)
			parent->right_ = cur;
		else
			parent->left_ = cur;
		cur->parent_ = parent;

		//2.新节点插入后,红黑树的性质3可能被破坏(不能有连续的两个红色节点)
		while (parent != head && RED == parent->color_)
		{
			Node* Grandfather = parent->parent_;
			if (parent == Grandfather->left_)
			{
				Node* uncle = Grandfather->right_;
				if (uncle && uncle->color_ == RED)
				{
					//情况1
					parent->color_ = BLACK;
					uncle->color_ = BLACK;
					Grandfather->color_ = RED;

					cur = Grandfather;
					parent = cur->parent_;
				}
				else
				{
					//情况2和情况3
					//情况3
					if (cur == parent->right_)
					{
						RotateLeft(parent);
						swap(parent, cur);
					}

					//情况2
					parent->color_ = BLACK;
					Grandfather->color_ = RED;
					RotateRight(Grandfather);
				}
			}
			else
			{
				//情况1情况2情况3的反情况
				Node* uncle = parent->left_;
				if (uncle && uncle->color_ == RED)
				{
					parent->color_ = BLACK;
					uncle->color_ = BLACK;
					Grandfather->color_ = RED;

					//如果Grandfather有双亲,则还需要向上更新
					cur = Grandfather;
					parent = cur->parent_;
				}
				else
				{
					if (cur == parent->left_)
					{
						RotateRight(parent);
						swap(cur, parent);
					}

					parent->color_ = BLACK;
					Grandfather->color_ = RED;
					RotateLeft(Grandfather);
				}
			}
		}

		root->color_ = BLACK;
		head->left_ = LeftMost();
		head->right_ = RightMost();
		return true;
	}

    //判断红黑树的创建有没有违反性质
	bool IsRBTree()
	{
		Node* root = GetRoot();

		//空树
		if (nullptr == root)
			return true;

		//验证性质2
		if (BLACK != root->color_)
		{
			cout << "违反性质2:根节点必须是黑色的。" << endl;
			return false;
		}

		//验证性质3和性质4,先验证性质3
		int BlackCount = 0;
		Node* cur = root;
		while (cur)
		{
			if (BLACK == cur->color_)
				BlackCount++;
			cur = cur->left_;
		}
		//检测其他路径的黑色节点数是否和最左侧路径的相同
		int PathCount = 0;
		return _IsRBTree(root, BlackCount, PathCount);
	}
private:

	bool _IsRBTree(Node* root, int BlackCount, int PathCount)
	{
		if (nullptr == root)
			return true;

		if (BLACK == root->color_)
			PathCount++;

		Node* parent = root->parent_;
		if (parent != head && RED == parent->color_ && RED == root->color_)
		{
			cout << "违反性质3:不能有两个连续的红色节点。" << endl;
			return false;
		}

		//当左右子树都为空时,说明走到路径尽头,判断黑色节点数是否相同
		if (nullptr == root->left_ && nullptr == root->right_)
		{
			if (PathCount != BlackCount)
			{
				cout << "违反性质4:每一条路径上的黑色节点数目相同。" << endl;
				return false;
			}
		}

		return _IsRBTree(root->left_, BlackCount, PathCount) &&
			_IsRBTree(root->right_, BlackCount, PathCount);
	}

	void Destory(Node* Proot)
	{
		if (Proot)
		{
			Destory(Proot->left_);
			Destory(Proot->right_);
			delete Proot;
			Proot = nullptr;
		}
	}

	//中序遍历
	void _InOrder(Node* Proot)
	{
		if (Proot)
		{
			_InOrder(Proot->left_);
			cout << Proot->val_ << " ";
			_InOrder(Proot->right_);
		}
	}

	Node* LeftMost()
	{
		Node* cur = GetRoot();
		
		if (nullptr == cur)
			return head;

		while (cur->left_)
			cur = cur->left_;

		return cur;
	}

	Node* RightMost()
	{
		Node* cur = GetRoot();

		if (nullptr == cur)
			return head;

		while (cur->right_)
			cur = cur->right_;

		return cur;
	}

	//左单旋
	void RotateLeft(Node* parent)
	{
		Node* subR = parent->right_;
		Node* subRL = subR->left_;

		parent->right_ = subRL;
		subR->left_ = parent;

		if (subRL)
			subRL->parent_ = parent;
		Node* pparent = parent->parent_;
		parent->parent_ = subR;
		subR->parent_ = pparent;

		if (head == pparent)
			head->parent_ = subR;
		else
		{
			if (parent == pparent->left_)
				pparent->left_ = subR;
			else
				pparent->right_ = subR;
		}
	}

	//右单旋
	void RotateRight(Node* parent)
	{
		Node* subL = parent->left_;
		Node* subLR = subL->right_;

		parent->left_ = subLR;
		subL->right_ = parent;

		if (subLR)
			subLR->parent_ = parent;
		Node* pparent = parent->parent_;
		parent->parent_ = subL;
		subL->parent_ = pparent;

		if (head == pparent)
			head->parent_ = subL;
		else
		{
			if (parent == pparent->left_)
				pparent->left_ = subL;
			else
				pparent->right_ = subL;
		}
	}

	//获取根节点
	Node*& GetRoot()
	{
		return head->parent_;
	}
private:
	Node* head;
};

void TestRBTree()
{
	int a[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9 };
	RBTree<int> t;
	for (auto e : a)
	{
		t.Insert(e);
	}
	t.InOrder();

	if (t.IsRBTree())
		cout << "红黑书创建完成!" << endl;
	else
		cout << "红黑树创建失败!" << endl;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值