16 - 12 - 14 红黑树(一)(性质、插入)

来源:互联网 发布:手机卡没办法收到网络 编辑:程序博客网 时间:2024/06/10 07:21

—-红黑树是2-3树的一种简单高效的实现,他巧妙地使用颜色标记来替代2-3树中比较难处理的3-node节点问题

定义
红黑树的主要是像是对2-3查找树进行编码,尤其是对2-3查找树中的3-nodes节点添加额外的信息。红黑树中将节点之间的链接分为两种不同类型,红色链接,他用来链接两个2-nodes节点来表示一个3-nodes节点。黑色链接用来链接普通的2-3节点。特别的,使用红色链接的两个2-nodes来表示一个3-nodes节点,并且向左倾斜,即一个2-node是另一个2-node的左子节点。这种做法的好处是查找的时候不用做任何修改,和普通的二叉查找树相同。

五个性质:
性质1. 节点是红色或黑色。

性质2. 根是黑色。

性质3. 所有叶子都是黑色(叶子是NIL节点)。

性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

性质5. 从任一节点到其每个叶子的所有简单路径 都包含相同数目的黑色节点。

红黑树数据结构定义:

typedef bool _Rb_tree_Color_type;const _Rb_tree_Color_type _S_rb_tree_red = false;const _Rb_tree_Color_type _S_rb_tree_black = true;struct _Rb_tree_node_base{  typedef _Rb_tree_Color_type _Color_type;  typedef _Rb_tree_node_base* _Base_ptr;  _Color_type _M_color;  _Base_ptr _M_parent;  _Base_ptr _M_left;  _Base_ptr _M_right;  static _Base_ptr _S_minimum(_Base_ptr __x)  {    while (__x->_M_left != 0) __x = __x->_M_left;    return __x;  }  static _Base_ptr _S_maximum(_Base_ptr __x)  {    while (__x->_M_right != 0) __x = __x->_M_right;    return __x;  }};template <class _Value>struct _Rb_tree_node : public _Rb_tree_node_base{  typedef _Rb_tree_node<_Value>* _Link_type;  _Value _M_value_field;};

查找:

/*红黑树是一种特殊的二叉查找树,他的查找方法也和二叉查找树一样,不需要做太多更改。但是由于红黑树比一般的二叉查找树具有更好的平衡,所以查找起来更快。*///查找获取指定的值,override是重载?喵喵喵??public override TValue Get(TKey key){    return GetValue(root, key);}private TValue GetValue(Node node, TKey key){    if (node == null) return default(TValue);    int cmp = key.CompareTo(node.Key);    if (cmp == 0) return node.Value;    else if (cmp > 0) return GetValue(node.Right, key);    else return GetValue(node.Left, key);}

平衡化

//左旋转private Node RotateLeft(Node h){    Node x = h.Right;    //将x的左节点复制给h右节点    h.Right = x.Left;    //将h复制给x右节点    x.Left = h;    x.Color = h.Color;    h.Color = RED;    return x;}

这里写图片描述


//右旋转private Node RotateRight(Node h){    Node x = h.Left;    h.Left = x.Right;    x.Right = h;    x.Color = h.Color;    h.Color = RED;    return x;}

这里写图片描述

*
*
颜色反转
对于树的旋转,能保持不变的只有原树的搜索性质,而原树的红黑性质则不能保持,
在红黑树的数据插入和删除后可利用旋转和颜色重涂来恢复树的红黑性质。
在对红黑树进行插入操作时,我们一般总是插入红色的结点,因为这样可以在插入过程中尽量避免对树的调整。
那么,我们插入一个结点后,可能会使原树的哪些性质改变列?
如果插入的结点是根结点,性质2会被破坏,如果插入结点的父结点是红色,则会破坏性质4。
因此,总而言之,插入一个红色结点只会破坏性质2或性质4。
性质:–1)每个结点要么是红的,要么是黑的。
———-2)根结点是黑的。
———-3)每个叶结点,即空结点(NIL)是黑的。
———-4)如果一个结点是红的,那么它的俩个儿子都是黑的。
———-5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点)

回复策略:
其一、把出现违背红黑树性质的结点向上移,如果能移到根结点,那么很容易就能通过直接修改根结点来恢复红黑树的性质。直接通过修改根结点来恢复红黑树应满足的性质。
其二、穷举所有的可能性,之后把能归于同一类方法处理的归为同一类,不能直接处理的化归到下面的几种情况,
**情况1:插入的是根结点。(整棵树的第一个节点)
因为原树是空树
对策:直接把此结点涂为黑色。
**情况2:插入的结点的父结点是黑色。
此不会违反性质2和性质4,红黑树没有被破坏。
对策:什么也不做。
**情况3:当前结点的父结点是红色且祖父结点的另一个子结点(叔叔结点)是红色。
此时父结点的父结点一定存在,否则插入前就已不是红黑树。
与此同时,又分为父结点是祖父结点的左子还是右子,对于对称性,我们只要解开一个方向就可以了。

在此,我们只考虑父结点为祖父左子的情况。
同时,还可以分为当前结点是其父结点的左子还是右子,但是处理方式是一样的。我们将此归为同一类。
变化前→:
变化后:

**情况4:当前节点的父节点是红色,叔叔节点是黑色,当前节点是其父节点的右子
对策:当前节点的父节点做为新的当前节点,以新当前节点为支点左旋。
如下图所示,变化前[插入7节点]:
变化前→:
变化后→:

**情况5:当前节点的父节点是红色,叔叔节点是黑色,当前节点是其父节点的左子
解法:父节点变为黑色,祖父节点变为红色,在祖父节点为支点右旋
如下图所示[插入2节点]
变化前→:
变化后→:


鸣谢:
htp://www.cnblogs.com/yangecnu/p/Introduce-Red-Black-Tree.html
htp://blog.csdn.net/aircattle/article/details/52347955
htp://www.cnblogs.com/v-July-v/archive/2010/12/29/1983707.html
htp://www.cnblogs.com/yangecnu/p/Introduce-Red-Black-Tree.html
htp://blog.csdn.net/yhl_leo/article/details/50099843
htp://algs4.cs.princeton.edu/33balanced/
htp://blog.csdn.net/haidao2009/article/details/8076970

1 0