红黑树—Red Black Tree
2015-03-28 21:47
411 查看
红黑树是具有以下五条性质的二叉查找树:
每个结点要么是红的要么是黑的。
根结点是黑的。
每个叶结点(叶结点即指树尾端NIL指针或NULL结点)都是黑的。
如果一个结点是红的,那么它的两个儿子都是黑的。
对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点。
正是由于红黑树的以上五个性质,使得其高度最多是2log(N+1),从而保证红黑树的查找、插入、删除的时间复杂度最坏为O(log n)。具体关于红黑树的基本介绍,以及插入操作,和删除操作的算法的具体分析可参考博文:教你透彻了解红黑树(其结构之法、算法之道系列文章整体不错,可以多多参考学习)。
在插入、删除过程中最关键的就是时刻保证RBT的五个性质。
以下主要给出RBT的插入算法的具体实现,删除操作目前还没彻底弄清楚,后续再补充。其中的左旋转,右旋转,以及双旋转操作与平衡二叉树中的操作一样,
具体见:平衡二叉树(AVLTree)。
插入操作:首先按查找二叉树的方法找到正确的插入位置,并将新节点X设为红色。则主要分为以下4中情况:
1、其父节点P为黑色,则直接插入,完成。
2、其父节点P为红色(则祖父节点GP一定为黑色),X为P(GP的左节点,为右节点时,对称情况)的左子节点(为右节点时,对称情况),其叔父节点S(即 GP的 右节点)为黑色,则执行一次左单旋转即可。 (对称情况执行一次右单旋转)。
3、其父节点P为红色(则祖父节点GP一定为黑色),X为P(GP的左节点,为右节点时,对称情况)的右子节点(为左节点时,对称情况),其叔父节点S(即 GP的
右节点)为黑色,则执行一次双旋转即可。 (对称情况类似执行一次双旋转)。
4、其父节点P为红色(则祖父节点GP一定为黑色),其叔父节点S为红色。 这种情况相对较为复杂。基本思路是,在插入新节点的自顶向下遍历过程中,将遇到的所有
双红儿子节点(其父节点一定为黑)的情况进行颜色翻转,即将父节点设为红,两儿子改为黑,从而将第4种情况转化为2或3的情况。
具体代码如下:
每个结点要么是红的要么是黑的。
根结点是黑的。
每个叶结点(叶结点即指树尾端NIL指针或NULL结点)都是黑的。
如果一个结点是红的,那么它的两个儿子都是黑的。
对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点。
正是由于红黑树的以上五个性质,使得其高度最多是2log(N+1),从而保证红黑树的查找、插入、删除的时间复杂度最坏为O(log n)。具体关于红黑树的基本介绍,以及插入操作,和删除操作的算法的具体分析可参考博文:教你透彻了解红黑树(其结构之法、算法之道系列文章整体不错,可以多多参考学习)。
在插入、删除过程中最关键的就是时刻保证RBT的五个性质。
以下主要给出RBT的插入算法的具体实现,删除操作目前还没彻底弄清楚,后续再补充。其中的左旋转,右旋转,以及双旋转操作与平衡二叉树中的操作一样,
具体见:平衡二叉树(AVLTree)。
插入操作:首先按查找二叉树的方法找到正确的插入位置,并将新节点X设为红色。则主要分为以下4中情况:
1、其父节点P为黑色,则直接插入,完成。
2、其父节点P为红色(则祖父节点GP一定为黑色),X为P(GP的左节点,为右节点时,对称情况)的左子节点(为右节点时,对称情况),其叔父节点S(即 GP的 右节点)为黑色,则执行一次左单旋转即可。 (对称情况执行一次右单旋转)。
3、其父节点P为红色(则祖父节点GP一定为黑色),X为P(GP的左节点,为右节点时,对称情况)的右子节点(为左节点时,对称情况),其叔父节点S(即 GP的
右节点)为黑色,则执行一次双旋转即可。 (对称情况类似执行一次双旋转)。
4、其父节点P为红色(则祖父节点GP一定为黑色),其叔父节点S为红色。 这种情况相对较为复杂。基本思路是,在插入新节点的自顶向下遍历过程中,将遇到的所有
双红儿子节点(其父节点一定为黑)的情况进行颜色翻转,即将父节点设为红,两儿子改为黑,从而将第4种情况转化为2或3的情况。
具体代码如下:
<span style="font-size:18px;">typedef enum ColorType {Red,Black} ColorType; typedef int ElementType; typedef struct RedBlackNode* RedBlackTree; typedef struct RedBlackTree Position; //节点 struct RedBlackNode { ElementType Element;//节点value值 RedBlackTree Left;//节点左指针 RedBlackTree Right;//节点右指针 ColorType Color;//节点颜色 }; /*旋转处理函数 根据需要进行单旋转(双旋转由两次单旋转完成) 参数: Item:新节点value值 Parent:插入新节点后的曾祖父节点 返回值: 旋转后的新树根(新节点的祖父节点)指针 */ static Position Rotate(ElementType Item,Position Parent) { if(Item<Parent->Element) return Parent->Left=Item<Parent->Left->Element? SingleRotateWithLeft(Parent->Left)://“一”形 SingleRotateWithRight(Parent->Left);//“之”形 else return Parent->Right=Item>Parent->Right->Element? SingleRotateWithRight(Parent->Right)://“一”形 SingleRotateWithLeft(Parent->Right);//“之”形 } static Position X,P,GP,GGP; /*树形调整函数*/ static void HandleRrorient(ElementType Item,RedBlackTree T) { //在自顶向下遍历时遇到双子节点均为红时,执行颜色翻转 X->Color=Red; X->Left->Color=Black; X->Right->Color=Black; if(P->Color==Red)//当父节点需要执行旋转操作 { GP->Color=Red; if(Item<P->Element != P->Element<GP->Element)//为”之“形,需要执行双旋转 P=Rotate(Item,GP);//对X和P执行一次单旋转(双旋转的第一次单旋转) X=Rotate(Item,GGP);//为”一“形,旋转后X为新子树的树根 X->Color=Black;//确保树根为黑色 } } RedBlackTree Insert(ElementType Item ,RedBlackTree T) { X=P=GP=GGP=T; /*Position NullNode=malloc(sizeof(struct RedBlackNode)); NullNode->Left=Right=NULL; NullNode->Color=Red; */ NullNode->Element=Item; while(X->Element!=Item && X!=NullNode)//自定向下遍历,并处理双红儿子节点,以及带来的旋转操作 { GGP=GP;GP=P;P=X; if(X<X->Element) X=X->Left; else X=X->Right; if(X->Left->Color==Red && X->Right->Color==Red)//双红儿子节点 HandleRrorient(Item,T); } if(X!=NullNode)//原来一存在该值的节点 return NullNode; X=malloc(sizeof(struct RedBlackNode)); if(X=NULL) printf("Out of space \n"); X->Element=Item; X->Left=X->Right=NullNode; //将新节点插入到树叶 if(Item<P->Element) P->Left=X; else P->Right=X; //最后插入节点后可能使得不满足红黑树的性质,因此需要最后一次调整(因为已不存在其叔父节点为红的情况,因此只需要进行一次单或者双旋转即可) HandleRrorient(Item,T); return T; } </span>
相关文章推荐
- 自平衡二叉查找树(二)-----------红黑树(redblack tree)分析和代码实现
- 红黑树(Red Black Tree)
- 红黑树(Red-Black Tree)
- 红黑树(Red Black Tree)
- C++数据结构 之 红黑树_Red Black Tree
- 红黑树(RedBlackTree)实现
- 红黑树(Red Black Tree)
- 红黑树(red black tree)的实现
- 红黑树(Red Black Tree)
- 红黑树Red-Black-Tree
- 红黑树(Red Black Tree)
- 红黑树(red black tree)
- 红黑树(Red Black Tree) (2012-05-31 22:02)
- Red Black Tree(红黑树)
- [转载]红黑树(Red Black Tree)
- 红黑树(red black tree) Common Lisp 实现
- 红黑树(Red Black Tree)
- 红黑树(RedblackTree)上--增加节点
- 红黑树(Red Black Tree)
- RedBlackTree 红黑树——接力写