C++-红黑树的插入和删除实现

Posted 天津 唐秙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++-红黑树的插入和删除实现相关的知识,希望对你有一定的参考价值。

红黑树的插入和删除实现

代码实现

#include <iostream>
#include <vector>

using namespace std;

typedef enum{RED = 0, BLACK = 1}Color_Type;

template <class Type>
class RBTree;

template<class Type>
class RBNode
{
	friend class RBTree<Type>;
public:
	RBNode(Type d) :data(d), leftChild(nullptr), rightChild(nullptr), parent(nullptr), color(RED)
	{}
	~RBNode()
	{}
private:
	Type data;
	RBNode *leftChild;
	RBNode *rightChild;
	RBNode *parent;
	Color_Type color;
};

template <class Type>
class RBTree
{
public:
	RBTree() :root(Nil), Nil(_Buynode())
	{
		Nil->leftChild = Nil->rightChild = Nil->parent = nullptr;
		Nil->color = BLACK;
	}

public:
	bool Insert(const Type &x)
	{
		return Insert(root, x);
	}
	bool Remove(const Type &x)
	{
		return Remove(root, x);
	}

protected:
	bool Insert(RBNode<Type> *&t, const Type &x);
	bool Remove(RBNode<Type> *&t, const Type &x);
	RBNode<Type>* _Buynode(const Type &x = Type())
	{
		RBNode<Type> *s = new RBNode<Type>(x);
		s->leftChild = s->rightChild = s->parent = Nil;
		return s;
	}
protected:
	void Insert_Fixup(RBNode<Type> *&t, RBNode<Type> *x);
	void Remove_Fixup(RBNode<Type> *&t, RBNode<Type> *key);
protected:
	void RotateRight(RBNode<Type> *&t, RBNode<Type> *x)
	{
		RBNode<Type> *y = x->leftChild;
		x->leftChild = y->rightChild;
		if (y->rightChild != Nil)
			y->rightChild->parent = x;

		y->rightChild = x;
		if (x == t)
			t = y;
		else if (x == x->parent->leftChild)
			x->parent->leftChild = y;
		else
			x->parent->rightChild = y;

		y->parent = x->parent;
		x->parent = y;
	}

	void RotateLeft(RBNode<Type> *&t, RBNode<Type> *x)
	{
		RBNode<Type> *y = x->rightChild;
		x->rightChild = y->leftChild;
		if (y->leftChild != Nil)//如果y存在左子树,则把y的左子树和x连接
			y->leftChild->parent = x;

		y->leftChild = x;
		if (x == t)
			t = y;
		else if (x == x->parent->leftChild)
			x->parent->leftChild = y;
		else
			x->parent->rightChild = y;

		y->parent = x->parent;
		x->parent = y;
	}

private:
	RBNode<Type> *Nil;
	RBNode<Type> *root;
};

template <class Type>
bool RBTree<Type>::Insert(RBNode<Type> *&t, const Type &x)
{
	RBNode<Type> *pr = Nil;//父节点指针
	RBNode <Type> *p = t;//当前节点指针
	while (p != Nil)
	{
		if (x == p->data)//如果已经存在则不能插入
			return false;
		pr = p;//保存父节点
		if (x < p->data)
			p = p->leftChild;//向左子树中找
		else
			p = p->rightChild;//向右子树中找
	}

	p = _Buynode(x);//购买节点

	if (pr == Nil)//如果父节点也是空的,那么t是根节点
		t = p;//将购买的节点给根节点
	else
	{
		if (x < pr->data)
			pr->leftChild = p;
		else
			pr->rightChild = p;
		p->parent = pr;
	}

	Insert_Fixup(t, p);//调整平衡 t是根节点 p是插入的节点
	return true;
}

template <class Type>
void RBTree<Type>::Insert_Fixup(RBNode<Type> *&t, RBNode<Type> *x)
{
	while (x->parent->color == RED)
	{
		RBNode<Type> *s;
		if (x->parent == x->parent->parent->leftChild)
		{
			//父节点是左分支

			s = x->parent->parent->rightChild;// s是父节点的兄弟节点
			if (s->color == RED)//父节点的兄弟节点是红的
			{
				//状况三
				x->parent->color = BLACK;
				s->color = BLACK;
				x->parent->parent->color = RED;
				x = x->parent->parent;
			}
			else//父节点的兄弟节点是黑的
			{
				if (x == x->parent->rightChild)//x是右节点
				{
					//状况二
					x = x->parent;
					RotateLeft(t, x);//左旋转
				}
				//状况一
				x->parent->color = BLACK;
				x->parent->parent->color = RED;
				RotateRight(t, x->parent->parent);
			}
		}
		else
		{
			//父节点是右分支
			s = x->parent->parent->leftChild;//父节点的兄弟节点
			if (s->color == RED)
			{
				//状况三
				x->parent->color = BLACK;
				s->color = BLACK;
				x->parent->parent->color = RED;
				x = x->parent->parent;
			}
			else//兄弟节点是黑的
			{
				if (x == x->parent->leftChild)
				{
					//状况二
					x = x->parent;
					RotateRight(t, x);
				}
				//状况一
				x->parent->color = BLACK;
				x->parent->parent->color = RED;
				RotateLeft(t, x->parent->parent);
			}
		}
	}
	t->color = BLACK;
}

template<class Type>
bool RBTree<Type>::Remove(RBNode<Type> *&t, const Type &key)
{
	RBNode<Type> *p = t;
	RBNode<Type> *q;
	//p找到目标元素key的节点   或者  p为Nil没找到
	while (p != Nil)
	{
		if (key == p->data)
			break;
		if (key < p->data)
			p = p->leftChild;
		else
			p = p->rightChild;
	}

	//排除了p为Nil的情况
	if (p == Nil)
		return false;

	//p找到目标元素key的节点
	//要删除节点的左子树和右子树都有节点
	if (p->leftChild != Nil && p->rightChild != Nil)
	{
		q = p->leftChild;
		while (q->rightChild != Nil)
			q = q->rightChild;

		p->data = q->data;
		p = q;
	}

	if (p->leftChild != Nil)
		q = p->leftChild;
	else
		q = p->rightChild;

	//从上向下连接
	if (p == p->parent->leftChild)
		p->parent->leftChild = q;
	else
		p->parent->rightChild = q;

	//连接前驱节点
	q->parent = p->parent;

	//调整平衡
	if (p->color == BLACK)
		Remove_Fixup(t, q);

	//删除节点
	delete p;
	return true;
}

template<class Type>
void RBTree<Type>::Remove_Fixup(RBNode<Type> *&t, RBNode<Type> *x)
{
	RBNode<Type> *w;//兄弟节点
	while (x != t && x->color == BLACK)
	{
		if (x == x->parent->leftChild)
		{
			//删除节点在左分支
			w = x->parent->rightChild;

			//情形四
			if (w->color == RED)
			{
				w->color = BLACK;
				x->parent->color = RED;
				RotateLeft(t, x->parent);
				w = x->parent->rightChild;
			}
			//情形三
			if (w->leftChild == Nil && w->rightChild == Nil)
			{
				x->parent->color = BLACK;
				w->color = RED;
				x = x->parent;
			}
			else
			{
				//情形二
				if (w->leftChild != Nil)
				{
					w->color = RED;
					w->leftChild->color = BLACK;
					w = w->leftChild;
					RotateRight(t, w->parent);
				}
				//情形一
				w->color = x->parent->color;
				x->parent->color = BLACK;
				w->rightChild->color = BLACK;
				RotateLeft(t, x->parent);
				x = t;
			}
		}
		else
		{
			//删除的节点在右分支
			w = x->parent->leftChild;

			//情形四
			if (w->color == RED)
			{
				w->color = BLACK;
				x->parent->color = RED;
				RotateRight(t, x->parent);
				w = x->parent->leftChild;
			}

			//情形三
			if (w->leftChild == Nil && w->rightChild == Nil)
			{
				w->color = RED;
				x->parent->color = BLACK;
				x = x->parent;
			}
			else
			{
				//情形二
				if (w->rightChild != Nil)
				{
					w->color = RED;
					w->rightChild->color = BLACK;
					w = w->rightChild;
					RotateLeft(t, w->parent);
				}
				//情形一
				w->color = x->parent->color;
				x->parent->color = BLACK;
				w->leftChild->color = BLACK;
				RotateRight(t, x->parent);
				x = t;
			}
		}
	}
	x->color;
}

void main()
{
	vector<int> iv = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };
	RBTree<int> rb;

	for (const auto &e : iv)
		rb.Insert(e);

	rb.Remove(5);
	rb.Remove(7);
	rb.Remove(6);

	return;
}

以上是关于C++-红黑树的插入和删除实现的主要内容,如果未能解决你的问题,请参考以下文章

如何轻松记住红黑树的插入和删除?

数据结构备忘录:红黑树的插入与删除

红黑树的插入与删除

红黑树:删除操作

数据结构 - 红黑树(Red Black Tree)删除详解与实现(Java)

红黑树的增加(插入)和删除