算法导论——红黑树
2018-03-18 07:47
204 查看
#include<stdio.h> #include<iostream> #include<stdlib.h> using namespace std; enum Color{RED, BLACK}; const int Length = 10; typedef struct RB { int key; RB *parent; RB *left; RB *right; Color color; }RBTreeNode, *RBTree; RBTree NIL = NULL; void RBInsertFix(RBTree &T, RBTree node); void LeftRotate(RBTree &T, RBTree x); void RightRotate(RBTree &T, RBTree x); void RBInsert(RBTree &T, int num); void RBTransPlant(RBTree &T, RBTree u, RBTree v); void RBDeleteFix(RBTree &T, RBTree x); void RBDelete(RBTree &T, RBTree Node); void InorderWalk(RBTree T); RBTree RBTreeMinimum(RBTree T); void InitRBTree(RBTree &T, int num[]); RBTree Tree_Search(RBTree T ,int k); //寻找数k是否在树中,且返回数k的地址 int main() { RBTree T; int num[Length] ={12, 2, 34, 56, 26, 8, 31, 6, 20, 3}; InitRBTree(T, num); InorderWalk(T); printf("\n\n-----------删除操作后-------------\n"); RBDelete(T,Tree_Search(T,2)); RBDelete(T,Tree_Search(T,56)); RBDelete(T,Tree_Search(T,3)); RBDelete(T,Tree_Search(T,34)); InorderWalk(T); } RBTree Tree_Search(RBTree T ,int k) //寻找数k是否在树中,且返回数k的地址 { while(T !=NIL && T->key != k) { if ( k < T->key) T=T->left; else T=T->right; } if ( T == NIL) { return NULL; } else { return T; } } void RightRotate(RBTree &T, RBTree x) { RBTree y = x->left; x->left = y->right; if(y->right != NIL) y->right->parent = x; y->parent = x->parent; if(x->parent == NIL) T = y; else if(x == x->parent->left) x->parent->left = y; else x->parent->right = y; y->right = x; x->parent = y; } void LeftRotate(RBTree &T, RBTree x) { RBTree y = x->right; x->right = y->left; if(y->left != NIL) y->left->parent = x; y->parent = x->parent; if(x->parent == NIL) T = y; else if(x == x->parent->left) x->parent->left = y; else x->parent->right = y; y->left = x; x->parent = y; } void RBInsert(RBTree &T, RBTree node) { RBTree y = NIL; RBTree x = T; while(x != NIL) { y = x; if(x->key > node->key) x = x->left; else x = x->right; } node->parent = y; if(y == NIL) T = node; else if(node->key < y->key) y->left = node; else y->right = node; RBInsertFix(T, node); } void RBInsertFix(RBTree &T, RBTree node) { RBTree y = NULL; while(node->parent->color == RED) { 4000 if(node->parent == node->parent->parent->left) { y = node->parent->parent->right; if(y->color == RED) { node->parent->color = BLACK; y->color = BLACK; node->parent->parent->color = RED; node = node->parent->parent; } else if(node == node->parent->right) { node = node->parent; LeftRotate(T, node); node->parent->color = BLACK; node->parent->parent->color = RED; RightRotate(T, node->parent->parent); } else { node->parent->color = BLACK; node->parent->parent->color = RED; RightRotate(T, node->parent->parent); } } else { y = node->parent->parent->left; if(y->color == RED) { node->parent->color = BLACK; y->color = BLACK; node->parent->parent->color = RED; node = node->parent->parent; } else if(node == node->parent->left) { node = node->parent; RightRotate(T, node); node->parent->color = BLACK; node->parent->parent->color = RED; LeftRotate(T, node->parent->parent); } else { node->parent->color = BLACK; node->parent->parent->color = RED; LeftRotate(T, node->parent->parent); } } } T->color = BLACK; } void InitRBTree(RBTree &T, int num[]) { RBTree node = NULL; NIL = (RBTree)malloc(sizeof(RBTreeNode)); NIL->left = NIL->right = NIL->parent = NULL; NIL->color = BLACK; T = NIL; for(int i = 0; i < Length; i++) { node = (RBTree)malloc(sizeof(RBTreeNode)); node->left = node->right = node->parent = NIL; node->key = num[i]; node->color = RED; RBInsert(T, node); } } void RBDeleteFix(RBTree &T, RBTree x) { RBTree w = NULL; while(x != T && x->color == BLACK) { if(x == x->parent->left) { w = x->parent->right; if(w->color == RED) { w->color = BLACK; x->parent->color = RED; LeftRotate(T, x->parent); w = x->parent->right; } if(w->left->color == BLACK && w->right->color == BLACK) { w->color = RED; x = x->parent; } else if(w->right->color == BLACK) { w->left->color = BLACK; w->color = RED; RightRotate(T, w); w = x->parent->right; w->color = x->parent->color; x->parent->color = BLACK; w->right->color = BLACK; LeftRotate(T, x->parent); x = T; } else { w->color = x->parent->color; x->parent->color = BLACK; w->right->color = BLACK; LeftRotate(T, x->parent); x = T; } } else { w = x->parent->left; if(w->color == RED) { w->color = BLACK; x->parent->color = RED; RightRotate(T, x->parent); w = x->parent->left; } if(w->right->color == BLACK && w->left->color == BLACK) { w->color = RED; x = x->parent; } else if(w->left->color == BLACK) { w->right->color = BLACK; w->color = RED; LeftRotate(T, w); w = x->parent->left; w->color = x->parent->color; x->parent->color = BLACK; w->left->color = BLACK; RightRotate(T, x->parent); x = T; } else { w->color = x->parent->color; x->parent->color = BLACK; w->left->color = BLACK; RightRotate(T, x->parent); x = T; } } } x->color = BLACK; } void RBTransPlant(RBTree &T, RBTree u, RBTree v) { if(u->parent == NIL) T = v; else if(u == u->parent->left) u->parent->left = v; else u->parent->right = v; v->parent = u->parent;//对v无条件执行 即使v是代表空的哨兵NIL 与二叉排序树的不同 } /*如果删除的结点y是红色的,则删除后的树仍然是保持红黑树的性质,因为树中各个结点的黑高度没有改变, 不存在两个相邻(父结点和子结点)的红色结点,y是红色不可能是根,所有根仍然是黑色。如果删除的结点z是黑色的, 则这个是破坏了红黑树的性质,需要调用RB_DELETE_FIXUP进行调整。从删除结点y的唯一孩子结点x或者是NIL处开始调整。 */ RBTree RBTreeMinimum(RBTree T) { while(T->left != NIL) T = T->left; return T; } void RBDelete(RBTree &T, RBTree Node) { int precolor; RBTree y = Node, x = NULL; precolor = y->color;//对y也就是z的初始颜色进行记录 if(Node->left == NIL) { x = Node->right;//若是z没有左子树 则可以直接将右子树取代z RBTransPlant(T, Node, Node->right); } else if(Node->right == NIL) { x = Node->left;//没有右子树 则直接用左子树取代z RBTransPlant(T, Node, Node->left); } else {//存在左右子树 y = RBTreeMinimum(Node->right);//找到Node的后继结点 即右子树中的最小值 precolor = y->color;//记录y的初始颜色 x = y->right;//因为后面的操作会将y变成z原有的颜色 所以违反性质的就是y的右孩子 if(y->parent == Node)//如果y是Node的孩子 x->parent = y;//x的父节点仍然是y else//作为后继结点的y不是Node的孩子 而存在在其右子树中 {//将y 用y的右子树代替 RBTransPlant(T, y, y->right); y->right = Node->right; y->right->parent = y; } RBTransPlant(T, Node, y);//将Node 用y代替 y->left = Node->left;//将Node的左子树转移到y上 因为y是Node的后继结点因此可以确保大小关系正确 y->left->parent = y; y->color = Node->color;///更改y的颜色,这样的话从y以上红黑树的性质都不会违反 //若之前的颜色是红色 则不会破坏树的性质 } if(precolor == BLACK) ///如果y原来的颜色是黑色,那么就意味着有一个黑色结点被覆盖了, ///红黑树的性质可能会被破坏(性质4或5),需要调整 RBDeleteFix(T, x); } void InorderWalk(RBTree T) { if(T == NIL) { return; } InorderWalk(T->left); printf("%d", T->key); if(T->color == BLACK) printf("-B "); else printf("-R "); InorderWalk(T->right); }
相关文章推荐
- 算法导论代码 第13章 红黑树
- 算法导论 红黑树 学习 插入(三)
- 算法导论红黑树
- 算法导论---红黑树删除详解
- 算法导论读后感-之红黑树的性质
- 《算法导论》学习笔记(4)——红黑树(c++语言实现)
- 算法导论笔记 红黑树(3)
- 《算法导论》读书笔记之第13章 红黑树
- 算法导论—红黑树
- 《算法导论》笔记--红黑树(二)
- 算法导论 红黑树基础知识
- 算法导论之红黑树的学习
- 《算法导论》学习总结 — 12. 第13章 红黑树(1)
- 《算法导论》第13章 红黑树
- 算法导论 红黑树 学习 删除(四)
- 《算法导论》读书笔记之第13章 红黑树 (转自博客园)
- 《算法导论》第13章 红黑树 个人笔记
- 算法导论读后感-之红黑树的性质
- 算法导论习题练习——红黑树的插入和删除
- 红黑树--删除 算法导论笔记