红黑树的实现

红黑树(RBT)的定义它或者是一颗空树,或者是具有一下性质的二叉查找树:

1.节点非红即黑。

2.根节点是黑色。

3.所有NULL结点称为叶子节点,且认为颜色为黑

4.所有红节点的子节点都为黑色。

5.从任一节点到其叶子节点的所有路径上都包含相同数目的黑节点。

                                                             

上面的定义理解起来有点费解,所以我总结了以下三点,只要满足以下三点就可以是红黑树了。

                                       1.根节点必须是黑树

                               2.红树不能连续链接,黑树可以。

                               3.每条路径上黑树的个数必须是相同的。

插入操作(Insert)

由于性质的约束:插入点不能为黑节点,应插入红节点。因为你插入黑节点将破坏性质5,所以每次插入的点都是红结点,但是若他的父节点也为红,那就会破坏了性质4,所以要做一些“旋转”和一些节点的变色!另外为叙述方便,我们给要插入的节点分别定义如下:

             N(红色),父节点为P,祖父节点为G,叔节点为U

下边将一一列出所有插入时遇到的情况:

情况一:该树为空树,直接插入根结点的位置,违反性质1,把节点颜色有红改为黑即可

情况二:插入节点N的父节点P为黑色,不违反任何性质,无需做任何修改。

情况三:N为红,P为红,(祖节点一定存在,且为黑,下边同理)U也为红,这里不论P是G的左孩子,还是右孩子;不论N是P的左孩子,还是右孩子如下图所示:

操作:先把P和U变为黑色,然后G变为红色

                                                                                                                                                                      


情况四:N为红,P为红,U为黑,P为G的左孩子,N为P的左孩子(或者P为G的右孩子,N为P的左孩子;反正就是同向的)如下图所示:

操作:将P变黑,G变红,然后以p为轴右旋

                                                                                                                                                          

情况五:N为红,P为红,U为黑,P为G的左孩子,N为P的右孩子(或者P为G的右孩子,N为P的左孩子;反正两方向相反)。如下图所示:

 操作:首先以P为轴左旋,然后将p和N指向的地址交换,然后就转换为情况四                                    

                                                                                                                                                                                 


代码如下:


数据结构定义如下:

enum Colour
{
	RED,
	BLACK,
};

template<class K, class V>
struct RBTreeNode
{
	// 链接结构
	RBTreeNode<K, V>* _left;
	RBTreeNode<K, V>* _right;
	RBTreeNode<K, V>* _parent;

	// Key/Value
	K _key;
	V _value;

	// 颜色
	Colour _col;

	RBTreeNode(const K& key, const V& value, Colour col = RED)
		:_left(NULL)
		, _right(NULL)
		, _parent(NULL)
		, _col(col)
		, _key(key)
		, _value(value)

	{}
};
操作代码如下:

template<class K, class V>
class RBTree
{
	typedef RBTreeNode<K, V> Node;
public:
	RBTree()
		:_root(NULL)
	{}

	bool Insert(const K& key, const V& value)
	{
		//1.树为空
		if (_root == NULL)
		{
			_root = new Node(key, value, BLACK);
			return true;
		}

		// 查找位置,插入节点
		Node* parent = NULL;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(key, value, RED);
		if (parent->_key < key)
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_left = cur;
			cur->_parent = parent;
		}

		// 调整
		while (cur != _root && parent->_col == RED)   //这两个条件说明了cur一定存在parent 和 grandfather
		{
			Node* grandfather = parent->_parent;
			if (parent == grandfather->_left)
			{
				Node* uncle = grandfather->_right;

				// case1
				if (uncle && uncle->_col == RED)   //uncle存在且uncle的颜色为红色
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;

					cur = grandfather;
					parent = cur->_parent;
				}
				else // case2/case3    //uncle不存在 或 uncle存在但颜色为黑色
				{
					// case3->case2
					if (cur == parent->_right)
					{
						_RotateL(parent);    //先左旋在交换
						swap(cur, parent);     //交换cur和parent的地址,此时cur指向parent的地址,parent指向cur的地址
					}

					grandfather->_col = RED;
					parent->_col = BLACK;

					_RotateR(grandfather);    //在右旋
				}
			}
			else   //parent == grandfather->_right
			{
				Node* uncle = grandfather->_left;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;

					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (cur == parent->_left)
					{
						_RotateR(parent);
						swap(cur, parent);
					}

					grandfather->_col = RED;
					parent->_col = BLACK;

					_RotateL(grandfather);
				}
			}
		}

		_root->_col = BLACK;

		return true;
	}

	void _RotateL(Node* parent)		//左旋转
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;

		parent->_right = subRL;		//修改指针(1)
		if (subRL)
			subRL->_parent = parent;

		subR->_left = parent;	    //修改指针(2)
		subR->_parent = parent->_parent;
		parent->_parent = subR;

		if (subR->_parent == NULL)
		{
			_root = subR;
		}
		else
		{
			if (subR->_parent->_key > subR->_key)
			{
				subR->_parent->_left = subR;	//修改指针(3)
			}
			else
			{
				subR->_parent->_right = subR;
			}
		}
	}

	void _RotateR(Node* parent)    //右旋
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		parent->_left = subLR;
		if (subLR)
		{
			subLR->_parent = parent;
		}

		subL->_right = parent;
		subL->_parent = parent->_parent;
		parent->_parent = subL;

		if (subL->_parent == NULL)
		{
			_root = subL;
		}
		else
		{
			if (subL->_parent->_key > subL->_key)
			{
				subL->_parent->_left = subL;
			}
			else
			{
				subL->_parent->_right = subL;
			}
		}
	}

	void InOrder()
	{
		return _InOrder(_root);
	}

	void _InOrder(Node* root)
	{
		if (root == NULL)
		{
			return;
		}

		_InOrder(root->_left);
		cout << root->_key << " ";
		_InOrder(root->_right);
	}


protected:
	Node* _root;
};

以上仅是红黑树的插入操作和打印操作,希望以上代码能帮助到想学编程的童鞋。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中的红黑树实现主要是通过对节点进行变色和旋转来维持其特性。具体实现可以参考以下步骤: 1.定义红黑树节点类,包括节点值、颜色、左右子节点等属性。 2.定义红黑树类,包括根节点、插入节点、删除节点等方法。 3.在插入节点时,根据其父节点和父节点的兄弟节点进行变色和旋转,以维持红黑树的特性。 4.在删除节点时,同样需要进行变色和旋转,以保证删除后的树仍然是一颗红黑树。 以下是一个简单的Java红黑树实现示例: ```java public class RBNode<T extends Comparable<T>> { boolean color;//颜色 T key;//关键字(键值) RBNode<T> left;//左子节点 RBNode<T> right;//右子节点 RBNode<T> parent;//父节点 public RBNode(boolean color, T key, RBNode<T> parent, RBNode<T> left, RBNode<T> right) { this.color = color; this.key = key; this.parent = parent; this.left = left; this.right = right; } } public class RBTree<T extends Comparable<T>> { private RBNode<T> root;//根节点 //插入节点 public void insert(T key) { RBNode<T> node = new RBNode<T>(false, key, null, null, null); if (node != null) { insert(node); } } //插入节点 private void insert(RBNode<T> node) { RBNode<T> current = null;//当前节点 RBNode<T> x = this.root;//从根节点开始查找 //查找插入位置 while (x != null) { current = x; if (node.key.compareTo(x.key) < 0) { x = x.left; } else { x = x.right; } } node.parent = current; if (current != null) { if (node.key.compareTo(current.key) < 0) { current.left = node; } else { current.right = node; } } else { this.root = node; } //修正红黑树 insertFixUp(node); } //修正红黑树 private void insertFixUp(RBNode<T> node) { RBNode<T> parent, gparent;//父节点和祖父节点 //需要修正的条件:父节点存在,且父节点的颜色是红色 while (((parent = parentOf(node)) != null) && isRed(parent)) { gparent = parentOf(parent);//祖父节点 //父节点是祖父节点的左子节点 if (parent == gparent.left) { RBNode<T> uncle = gparent.right;//叔叔节点 //case1:叔叔节点也是红色 if ((uncle != null) && isRed(uncle)) { setBlack(parent); setBlack(uncle); setRed(gparent); node = gparent; continue; } //case2:叔叔节点是黑色,且当前节点是右子节点 if (node == parent.right) { RBNode<T> tmp; leftRotate(parent); tmp = parent; parent = node; node = tmp; } //case3:叔叔节点是黑色,且当前节点是左子节点 setBlack(parent); setRed(gparent); rightRotate(gparent); } else {//父节点是祖父节点的右子节点 RBNode<T> uncle = gparent.left;//叔叔节点 //case1:叔叔节点也是红色 if ((uncle != null) && isRed(uncle)) { setBlack(parent); setBlack(uncle); setRed(gparent); node = gparent; continue; } //case2:叔叔节点是黑色,且当前节点是左子节点 if (node == parent.left) { RBNode<T> tmp; rightRotate(parent); tmp = parent; parent = node; node = tmp; } //case3:叔叔节点是黑色,且当前节点是右子节点 setBlack(parent); setRed(gparent); leftRotate(gparent); } } setBlack(this.root);//将根节点设为黑色 } //左旋 private void leftRotate(RBNode<T> x) { RBNode<T> y = x.right; x.right = y.left; if (y.left != null) { y.left.parent = x; } y.parent = x.parent; if (x.parent == null) { this.root = y; } else { if (x.parent.left == x) { x.parent.left = y; } else { x.parent.right = y; } } y.left = x; x.parent = y; } //右旋 private void rightRotate(RBNode<T> y) { RBNode<T> x = y.left; y.left = x.right; if (x.right != null) { x.right.parent = y; } x.parent = y.parent; if (y.parent == null) { this.root = x; } else { if (y == y.parent.right) { y.parent.right = x; } else { y.parent.left = x; } } x.right = y; y.parent = x; } //获取节点的父节点 private RBNode<T> parentOf(RBNode<T> node) { return node != null ? node.parent : null; } //判断节点是否是红色 private boolean isRed(RBNode<T> node) { return (node != null) && node.color; } //设置节点为红色 private void setRed(RBNode<T> node) { if (node != null) { node.color = true; } } //设置节点为黑色 private void setBlack(RBNode<T> node) { if (node != null) { node.color = false; } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值