数据结构—红黑树(BRTree树)的认识

一、红黑树的概念:
  1. 红黑树:是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。
  2. 红黑树的性质:(一头一脚黑,黑同红不同
    (1)每个结点不是红色就是黑色
    (2)根节点是黑色的
    (3)如果一个节点是红色的,则它的两个孩子结点是黑色的
    (4)对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点
    (5) 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
二、模拟实现:

1.红黑树的节点定义

#include<iostream>
using namespace std;
typedef enum {RED=0,BLACK}Color_Type;

template<typename Type>
class RBTree;
template<typename Type>
class rb_iterator;

template<typename Type>
class RBTreeNode
{
	friend class RBtree<Type>;
	friend class rb_iterator<Type>;
public:
	RBTree(const Type& val = Type())
		:data(val), left(nullptr), right(nullptr), parent(nullptr), colour(RED)
	{}
	~RBTreeNode()
	{}
private:
	Type data;//数据
	RBTreeNode *left;//左孩子
	RBTreeNode *right;//右孩子
	RBTreeNode *parent;//父节点
	Color_Type colour;//颜色属性
};
  1. 迭代器的的实现
//迭代器的定义实现:

template<typename Type>
class rb_iterator
{
	typedef rb_iterator self;
public:
	rb_iterator(RBTreeNode<Type>* p, RBTreeNode<Type>* nil)
		:node(p), NIL(nil)
	{}
public:
	//运算符重载
	Type& operator*()
	{
		return node->date;
	}
	self& operator++()
	{
		increment();
		return *this;
	}
	self& operator--()
	{
		decrement();
		return *this;
	}
public:
	bool operator==(const rb_iterator &rbit)
	{
		return node == rbit.node;
	}
	bool operator!=(const rb_iterator &rbit)
	{
		return node != rbit.node();
	}
protected:
	void increment()
	{
		if (node->right != NIL)
		{
			node = node->right;
			while (node->left != NIL)
				node = node->left;
		}
		else
		{
			RBTreeNode<Type>* p = node->parent;
			while (node == p->right)
			{
				node = p;
				p = p->parent;
			}
			node = p;
		}
	}
	void decrement()
	{
		if (node->left != NIL)
		{
			node = node->left;
			while (node->right != NIL)
				node = node->right;
		}
		else
		{
			RBTreeNode<Type>*p = node->parent;
			while (node == p->left)
			{
				node = p;
				p = p->parent;
			}
			node = p;
		}
	}
private:
	RBTreeNode<Type>* node;
	RBTreeNode<Type>*NTL;
};
  1. BSTree树的形成
    (1**)红黑树的结构**:
    为了实现关联式容器简单,红黑树的实现中增加一个头结点,因为跟节点必须为黑色,为了与根节点进行区分,将头结点给成黑色,并且让头结点的 pParent 域指向红黑树的根节点,pLeft域指向红黑树中最小的节点,_pRight域指向红黑树中最大的节点。
    (2)红黑树的实现:
template<typename Type>
class RBTree
{
public:
	typedef rb_iterator<Type> iterator;

public:
	RBTree() :NIL(_Buynode()), end_node(_Buynode())
	{
		NIL->left = NIL->right = NIL->parent = NIL;
		NIL->colour = BLACK;
		end_node->left = end_node->right = end_node->parent = NIL;

		root = NIL;
	}

public:
	iterator begin()
	{
		RBTreeNode<Type> *p = root;
		while (p != NIL && p->left != NIL)
			p = p->left;
		return iterator(p, NIL);
	}
	iterator end()
	{
		return iterator(end_node, NIL);
	}

public:
	void set_endnode()
	{
		RBtreeNode<Type> *p = root;
		while (p != NIL&&p->right != NIL)
			p = p->right;
		p->right = end_node;
	}
	void insert(const Type& x)
	{
		insert(root, x);
	}
protected:
	void insert(RBTreeNode<Type> *&t, const Type& x)
	{
		//1.找到插入的位置
		RBTreeNode<Type> *pr = NIL;
		RBTreeNode<Type> *p = t;
		while (p != NIL)
		{
			if (x == p->data)
				return;
			pr = p;
			if (x < p->data)
			{
				p = p->left;
			}
			else
			{
				p = p->right;
			}
		}

		RBTreeNode<Type>* s = _Buynode(x);
		if (pr == NIL)
		{
			//第一次差入根节点
			t = s;
			t->parent = NIL;
		}
		else if (x < pr->data)
		{
			pr->left = s;
		}
		else
			pr->right = s;
		s->parent = pr;
		//2.平衡调整
		insert_fixup(t, s);
	}
protected:
	void insert_fixup(RBTreeNode<Type> *&t, RBTreeNode<Type> *x)
	{
		//x为新插节点,s为叔伯节点,p为父节点,g为祖父节点
		while (x->parent->colour)
		{
			RBTreeNode<Type> *s;
			if (x->parent == x->parent->parent->left) //左分支
			{
				s = x->parent->parent->right;

				if (s->color == RED) //状况3
				{
					x->parent->color = BLACK;
					s->color = BLACK;
					x->parent->parent->color = RED;
					x = x->parent->parent;
					continue;
				}
				else if (x == x->parent->right) //状况2  // <
				{
					x = x->parent;
					LeftRotate(t, x);
				}
				//状况1
				x->parent->color = BLACK;
				x->parent->parent->color = RED;
				RightRotate(t, x->parent->parent);
			}
			else //右分支
			{
				s = x->parent->parent->left;
				if (s->color == RED) 状况3
				{
					x->parent->color = BLACK;
					s->color = BLACK;
					x->parent->parent->color = RED;
					x = x->parent->parent;
					continue;
				}
				else if (x == x->parent->left) //状况2  // >
				{
					x = x->parent;
					RightRotate(t, x);
				}

				//状况1
				x->parent->color = BLACK;
				x->parent->parent->color = RED;
				LeftRotate(t, x->parent->parent);
			}
		}
		t->colour = BLACK;
		// 旋转方法都以p节点为轴点进行旋转
		void LeftRotate(RBTreeNode<Type> *&t, RBTreeNode<Type> *p)
		{
			RBTreeNode<Type> *s = p->right;
			p->right = s->left;
			if (s->left != NIL)
				s->left->parent = p;
			s->parent = p->parent;
			if (p->parent == NIL)
				t = s;
			else if (p == p->parent->left)
				p->parent->left = s;
			else
				p->parent->right = s;

			s->left = p;
			p->parent = s;
		}
		void RightRotate(RBTreeNode<Type> *&t, RBTreeNode<Type> *p)
		{
			RBTreeNode<Type> *s = p->left;
			p->left = s->right;
			if (s->right != NIL)
				s->right->parent = p;
			s->parent = p->parent;
			if (p->parent == NIL)
				t = s;
			else if (p == p->parent->left)
				p->parent->left = s;
			else
				p->parent->right = s;

			s->right = p;
			p->parent = s;
		}
	}

protected:
	RBTreeNode<Type>* _Buynode(const Type &val = Type())
	{
		RBTreeNode* _S = new RBTreeNode<Type>(val);
		_S->left = _S->right = _S->parsent = NIL;
		return _S;
	}

private:
	RBTreeNode<Type> *root;//根节点
	RBTreeNode<Type> *NIL;//叶子节点
	RBTreeNode<Type> *end_node;

};

int main()
{
	vector<int> v = { 10, 7, 4, 2, 80, 15, 5, 6, 11, 13, 12 };

	RBTree<int> rb;
	for (const auto &e : v)
		rb.insert(e);
	rb.set_endnode();

	RBTree<int>::iterator it = rb.begin();
	while (it != rb.end())
	{
		cout << *it << " ";
		++it;
	}

	return 0;
}
三、红黑树与AVL树的比较:

红黑树和AVL树都是高效的平衡二叉树,增删改查的时间复杂度都是O( logN),红黑树不追求绝对平衡,其只需保证最长路径不超过最短路径的2倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL树更优,而且红黑树实现比较简单,所以实际运用中红黑树更多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值