红黑树的c语言实现
2016-09-03 16:53
204 查看
不得不说《算法导论》是一本非常厉害的书!我主要参考了《算法导论》和网络上其他一些优秀的红黑书原理的资料,实现了这个红黑树的代码。很有意义,在整个过程中虽然大部分的时间还是看着书上的伪代码在敲c,但是整个原理已经大致在心中有了一个轮廓,为什么要这么实现红黑树那?前人是怎么想出来的那?路漫漫其修远兮,吾将上下而求索!希望自己有一天也能设计出这么精妙的数据结构算法。这篇文章之后我还将会实现一下avl树,这个树我一直耿耿于怀!先附上一些代码,再说说自己最深的感触。
这个地方我就不再一步一步地去解释原理了,书上包括很多的优秀的博客上都有红黑树详细的解释,我谈谈我在学习的过程中遇到的困难,第一首先要弄懂搜索二叉树的原理,包括插入和删除。知道这个之后我们明白了,在一些情况下,这个树的节点的左右子树可能出现不平衡的状况,导致二叉树的算法的性能大幅下滑,这个时候我们就想要去寻找一种自平衡的二叉树,希望在插入和删除的时候这个树可以自我调节,自我平衡。红黑树就是这样的一种树。而在实现的过程当中,删除的操作最为复杂,这个操作所需要的重要的思想就是x节点。很多思想在代码中并没有反映出来,如果之前位置的y节点的颜色是BLACK,那么这棵树的红黑五大性质就已经被破坏了,所以我们就需要调用rb_tree_delete_fixup来调整,最重要的思想就是,假设x节点自身拥有一重额外的黑色,这个黑色不会在代码上反映,但是却是非常重要的思想。也是这个地方让我思考了最久!我们所需要的做的就是,维护好其他的性质,最后将这一重额外的黑色除去!
此外非常推荐大家去看看JULY大神的红黑树的文章,非常详细,但是最重要的还是反复去看算法导论上的讲解,真的太厉害了。
/************************************************************************* > File Name: rb_tree.c > Author: jeff zhu > Mail: 908190355@qq.com > Created Time: 2016年08月30日 星期二 22时08分53秒 ************************************************************************/ #include <stdio.h> #include <limits.h> #include <malloc.h> #define RED 1 #define BLACK 2 #define NIL INT_MIN typedef int EleType; typedef struct rb_tree_node { struct rb_tree_node *parent; struct rb_tree_node *left; struct rb_tree_node *right; EleType key; int color; }NODE; typedef struct rb_tree { NODE *root; NODE *nil; }RBTREE; void init_rb_tree_root (RBTREE *T) ; NODE *create_rb_tree_node (RBTREE T , EleType key) ; void rb_tree_insert (RBTREE *T , NODE *x) ; void rotate_right (RBTREE *T , NODE *y) ; void rotate_left (RBTREE *T , NODE *x) ; void rb_tree_insert_fixup (RBTREE *T , NODE *x) ; void travel_tree (RBTREE *T , NODE *node) ; NODE* minimum_rb_tree (RBTREE *T , NODE *x) ; void rb_tree_delete_fixup (RBTREE *T , NODE *x) ; void rb_tree_delete (RBTREE *T , NODE *z) ; int main () { RBTREE T; init_rb_tree_root (&T); NODE *temp; int flag; while (scanf ("%d" , &flag) , flag != -1) { NODE *temp = create_rb_tree_node (T , flag); rb_tree_insert (&T , temp); } rb_tree_delete (&T , T.root); travel_tree (&T , T.root); } void init_rb_tree_root (RBTREE *T) { T->root = NULL; T->nil = (NODE *) malloc (sizeof (NODE)); T->nil->parent = NULL; T->nil->left = NULL; T->nil->right = NULL; T->nil->key = NIL; T->nil->color = BLACK; } NODE *create_rb_tree_node (RBTREE T , EleType key) { // create a red-black-tree and its default color is RED NODE *temp = (NODE *) malloc (sizeof (NODE)); temp->key = key; temp->color = RED; temp->parent = NULL; temp->left = T.nil; temp->right = T.nil; return temp; } void rb_tree_insert (RBTREE *T , NODE *x) { NODE *temp = T->root; NODE *log = T->nil; if (temp == NULL) { T->root = x; x->left = T->nil; x->right = T->nil; x->parent = T->nil; }else { while (temp != T->nil) { log = temp; if (x->key > temp->key) temp = temp->right; else temp = temp->left; } if (log->key < x->key) log->right = x; else log->left = x; x->parent = log; } rb_tree_insert_fixup (T , x); } void rb_tree_insert_fixup (RBTREE *T , NODE *x) { // this function is to fixup the rb-tree after calling rb_tree_insert while (x->parent->color == RED) { if (x->parent == x->parent->parent->left) { NODE *y = x->parent->parent->right; if (y->color == RED) { y->color = BLACK; x->parent->color = BLACK; x->parent->parent->color = RED; x = x->parent->parent; }else if (y->color == BLACK) { if (x == x->parent->right) { x = x->parent; rotate_left (T , x); } x->parent->color = BLACK; x->parent->parent->color = RED; rotate_right (T , x->parent->parent); } }else { NODE *y = x->parent->parent->left; if (y->color == RED) { y->color = BLACK; x->parent->color = BLACK; x->parent->parent->color = RED; x = x->parent->parent; }else if (y->color == BLACK) { if (x == x->parent->left) { x = x->parent; rotate_right (T , x); } x->parent->color = BLACK; x->parent->parent->color = RED; rotate_left (T , x->parent->parent); } } } T->root->color = BLACK; } void rotate_left (RBTREE *T , NODE *x) { NODE *y = x->right; x->right = y->left; if (y->left != T->nil) y->left->parent = x; y->parent = x->parent; if (x->parent == T->nil) T->root = y; else if (x == x->parent->left) x->parent->left = y; else x->parent->right = y; x->parent = y; y->left = x; } void rotate_right (RBTREE *T , NODE *y) { NODE *x = y->left; y->left = x->right; if (x->right != T->nil) x->right->parent = y; x->parent = y->parent; if (y->parent == T->nil) T->root = x; else if (y == y->parent->left) y->parent->left = x; else y->parent->right = x; y->parent = x; x->right = y; } void travel_tree (RBTREE *T , NODE *node) { if (node != T->nil) { travel_tree (T , node->left); printf ("this node's color is %d\n" , node->color); printf ("this node's key is %d\n" , node->key); printf ("\n"); travel_tree (T , node->right); } } void transplant (RBTREE *T , NODE *x , NODE *y) { if (x->parent == T->nil) T->root = y; else if (x == x->parent->left) x->parent->left = y; else x->parent->right = y; if (y != T->nil) y->parent = x->parent; } NODE* minimum_rb_tree (RBTREE *T , NODE *x) { NODE *y = T->nil; NODE *temp = x; while (temp != T->nil) { y = temp; temp = temp->left; } return y; } void rb_tree_delete (RBTREE *T , NODE *z) { NODE *y = z; NODE *x; int y_original_color = y->color; if (z->left == T->nil) { x = z->right; transplant (T , z , z->right); free (z); }else if (z->right == T->nil) { x = z->right; transplant (T , z , z->left); free (z); }else { y = minimum_rb_tree (T , z->right); y_original_color = y->color; x = y->right; if (y->parent == z) { x->parent = y; transplant (T , z , y); y->left = z->left; z->left->parent = y; y->color = z->color; free (z); }else { transplant (T , y , y->right); y->right = z->right; y->right->parent = y; transplant (T , z , y); y->left = z->left; y->left->parent = y; y->color = z->color; free (z); } } if (y_original_color == BLACK) rb_tree_delete_fixup (T , x); } void rb_tree_delete_fixup (RBTREE *T , NODE *x) { NODE *w; while (x != T->root && x->color == BLACK) { if (x == x->parent->left) { w = x->parent->right; if (w->color == RED) { w->color = BLACK; x->parent->color = RED; rotate_left (T , x->parent); w = x->parent->right; } if (w->left->color == BLACK && w->right->color == BLACK) { w->color == BLACK; x = x->parent; }else { if (w->left->color == RED && w->right->color == BLACK) { w->left->color == BLACK; w->color == RED; rotate_right (T , w); w = x->parent->right; } w->color = w->parent->color; w->parent->color = BLACK; w->right->color = BLACK; rotate_left (T , x->parent); x = T->root; } } else { w = x->parent->left; if (w->color == RED) { w->color = BLACK; x->parent->color = RED; rotate_right (T , x->parent); w = x->parent->left; } if (w->left->color == BLACK && w->right->color == BLACK) { w->color = RED; x = x->parent; }else { if (w->left->color == BLACK && w->right->color == RED) { w->color = RED; w->right->color = BLACK; rotate_right (T , w); w = x->parent->left; } w->color = w->parent->color; w->parent->color = BLACK; w->left->color = BLACK; rotate_right (T , x->parent); x = T->root; } } } if (x != T->nil) x->color = BLACK; }
这个地方我就不再一步一步地去解释原理了,书上包括很多的优秀的博客上都有红黑树详细的解释,我谈谈我在学习的过程中遇到的困难,第一首先要弄懂搜索二叉树的原理,包括插入和删除。知道这个之后我们明白了,在一些情况下,这个树的节点的左右子树可能出现不平衡的状况,导致二叉树的算法的性能大幅下滑,这个时候我们就想要去寻找一种自平衡的二叉树,希望在插入和删除的时候这个树可以自我调节,自我平衡。红黑树就是这样的一种树。而在实现的过程当中,删除的操作最为复杂,这个操作所需要的重要的思想就是x节点。很多思想在代码中并没有反映出来,如果之前位置的y节点的颜色是BLACK,那么这棵树的红黑五大性质就已经被破坏了,所以我们就需要调用rb_tree_delete_fixup来调整,最重要的思想就是,假设x节点自身拥有一重额外的黑色,这个黑色不会在代码上反映,但是却是非常重要的思想。也是这个地方让我思考了最久!我们所需要的做的就是,维护好其他的性质,最后将这一重额外的黑色除去!
此外非常推荐大家去看看JULY大神的红黑树的文章,非常详细,但是最重要的还是反复去看算法导论上的讲解,真的太厉害了。
相关文章推荐
- 红黑树及C语言实现
- 红黑树(C语言实现)
- 红黑树之 C语言的实现
- 《算法导论》中红黑树的C语言实现
- 浅谈红黑树(C语言代码实现)
- 算法导论学习---红黑树具体解释之插入(C语言实现)
- 红黑树及C语言实现
- 用c语言实现红黑树(依据算法导论上的方法)
- 红黑树(二)之 C语言的实现
- 红黑树(二)之 C语言的实现
- C语言实现红黑树
- 红黑树实现文件C语言
- 《算法导论》学习笔记(4)——红黑树(c语言实现)
- C语言实现红黑树
- C语言实现红黑树的实例代码
- 算法导论学习---红黑树详解之插入(C语言实现)
- 红黑树的C语言实现
- 红黑树(二)之 C语言的实现
- C语言实现红黑树
- 经典算法:红黑树的C语言实现 ( 插入 、删除 )