紅黑樹C語言實現

轉載:http://blog.csdn.net/v_JULY_v/article/details/6114226


前言:
    紅黑樹作爲一種經典而高級的數據結構,相信,已經被不少人實現過,但不是因爲程序不夠完善而無法運行,就是因爲程序完全沒有註釋,初學者根本就看不懂。
    此份紅黑樹的c源碼最初從linux-lib-rbtree.c而來,後經一網友那誰(http://www.cppblog.com/converse/)用c寫了出來。在此,向原作者表示敬意。但原來的程序存在沒有任何一行註釋。沒有一行註釋的程序,令程序的價值大打折扣。

    所以,我特把這份源碼放到了windows xp+vc 6.0上,一行一行的完善,一行一行的給它添加註釋,至此,紅黑樹c帶註釋的源碼,就擺在了您眼前,有不妥、不正之處,還望不吝指正。
------------

紅黑樹的六篇文章:

1、教你透徹瞭解紅黑樹
2、紅黑樹算法的實現與剖析
3、紅黑樹的c源碼實現與剖析
4、一步一圖一代碼,R-B Tree
5、紅黑樹插入和刪除結點的全程演示
6、紅黑樹的c++完整實現源碼

-------------------------

ok,咱們開始吧。
    相信,經過我前倆篇博文對紅黑樹的介紹,你應該對紅黑樹有了透徹的理解了(沒看過的朋友,可事先查上面的倆篇文章,或與此文的源碼剖析對應着看)。

    本套源碼剖析把重點放在紅黑樹的3種插入情況,與紅黑樹的4種刪除情況。其餘的能從略則儘量簡略。

目錄:
一、左旋代碼分析
二、右旋
三、紅黑樹查找結點
四、紅黑樹的插入
五、紅黑樹的3種插入情況
六、紅黑樹的刪除
七、紅黑樹的4種刪除情況
八、測試用例

好的,咱們還是先從樹的左旋、右旋代碼,開始(大部分分析,直接給註釋):

  1. //一、左旋代碼分析  
  2. /*----------------------------------------------------------- 
  3. |   node           right 
  4. |   / /    ==>     / / 
  5. |   a  right     node  y 
  6. |       / /       / /     
  7. |       b  y     a   b    //左旋 
  8. -----------------------------------------------------------*/  
  9. static rb_node_t* rb_rotate_left(rb_node_t* node, rb_node_t* root)  
  10. {  
  11.     rb_node_t* right = node->right;    //指定指針指向 right<--node->right  
  12.    
  13.     if ((node->right = right->left))    
  14.     {  
  15.         right->left->parent = node;  //好比上面的註釋圖,node成爲b的父母  
  16.     }  
  17.     right->left = node;   //node成爲right的左孩子  
  18.    
  19.     if ((right->parent = node->parent))  
  20.     {  
  21.         if (node == node->parent->right)  
  22.         {  
  23.             node->parent->right = right;  
  24.         }  
  25.         else  
  26.         {  
  27.             node->parent->left = right;  
  28.         }  
  29.     }  
  30.     else  
  31.     {  
  32.         root = right;  
  33.     }  
  34.     node->parent = right;  //right成爲node的父母  
  35.    
  36.     return root;  
  37. }  
  38.   
  39.   
  40. //二、右旋  
  41. /*----------------------------------------------------------- 
  42. |       node            left 
  43. |       / /             / / 
  44. |    left  y   ==>    a    node 
  45. |   / /                    / / 
  46. |  a   b                  b   y  //右旋與左旋差不多,分析略過 
  47. -----------------------------------------------------------*/  
  48. static rb_node_t* rb_rotate_right(rb_node_t* node, rb_node_t* root)  
  49. {  
  50.     rb_node_t* left = node->left;  
  51.    
  52.     if ((node->left = left->right))  
  53.     {  
  54.         left->right->parent = node;  
  55.     }  
  56.     left->right = node;  
  57.    
  58.     if ((left->parent = node->parent))  
  59.     {  
  60.         if (node == node->parent->right)  
  61.         {  
  62.             node->parent->right = left;  
  63.         }  
  64.         else  
  65.         {  
  66.             node->parent->left = left;  
  67.         }  
  68.     }  
  69.     else  
  70.     {  
  71.         root = left;  
  72.     }  
  73.     node->parent = left;  
  74.    
  75.     return root;  
  76. }  
  77.   
  78.   
  79. //三、紅黑樹查找結點  
  80. //----------------------------------------------------  
  81. //rb_search_auxiliary:查找  
  82. //rb_node_t* rb_search:返回找到的結點  
  83. //----------------------------------------------------  
  84. static rb_node_t* rb_search_auxiliary(key_t key, rb_node_t* root, rb_node_t** save)  
  85. {  
  86.     rb_node_t *node = root, *parent = NULL;  
  87.     int ret;  
  88.    
  89.     while (node)  
  90.     {  
  91.         parent = node;  
  92.         ret = node->key - key;  
  93.         if (0 < ret)  
  94.         {  
  95.             node = node->left;  
  96.         }  
  97.         else if (0 > ret)  
  98.         {  
  99.             node = node->right;  
  100.         }  
  101.         else  
  102.         {  
  103.             return node;  
  104.         }  
  105.     }  
  106.    
  107.     if (save)  
  108.     {  
  109.         *save = parent;  
  110.     }  
  111.    
  112.     return NULL;  
  113. }  
  114.   
  115. //返回上述rb_search_auxiliary查找結果  
  116. rb_node_t* rb_search(key_t key, rb_node_t* root)  
  117. {  
  118.     return rb_search_auxiliary(key, root, NULL);  
  119. }  
  120.   
  121.   
  122. //四、紅黑樹的插入  
  123. //---------------------------------------------------------  
  124. //紅黑樹的插入結點  
  125. rb_node_t* rb_insert(key_t key, data_t data, rb_node_t* root)  
  126. {  
  127.     rb_node_t *parent = NULL, *node;  
  128.    
  129.     parent = NULL;  
  130.     if ((node = rb_search_auxiliary(key, root, &parent)))  //調用rb_search_auxiliary找到插入結  
  131.   
  132. 點的地方  
  133.     {  
  134.         return root;  
  135.     }  
  136.    
  137.     node = rb_new_node(key, data);  //分配結點  
  138.     node->parent = parent;     
  139.     node->left = node->right = NULL;  
  140.     node->color = RED;  
  141.    
  142.     if (parent)  
  143.     {  
  144.         if (parent->key > key)  
  145.         {  
  146.             parent->left = node;  
  147.         }  
  148.         else  
  149.         {  
  150.             parent->right = node;  
  151.         }  
  152.     }  
  153.     else  
  154.     {  
  155.         root = node;  
  156.     }  
  157.    
  158.     return rb_insert_rebalance(node, root);   //插入結點後,調用rb_insert_rebalance修復紅黑樹  
  159.   
  160. 的性質  
  161. }  
  162.   
  163.   
  164. //五、紅黑樹的3種插入情況  
  165. //接下來,咱們重點分析針對紅黑樹插入的3種情況,而進行的修復工作。  
  166. //--------------------------------------------------------------  
  167. //紅黑樹修復插入的3種情況  
  168. //爲了在下面的註釋中表示方便,也爲了讓下述代碼與我的倆篇文章相對應,  
  169. //用z表示當前結點,p[z]表示父母、p[p[z]]表示祖父、y表示叔叔。  
  170. //--------------------------------------------------------------  
  171. static rb_node_t* rb_insert_rebalance(rb_node_t *node, rb_node_t *root)  
  172. {  
  173.     rb_node_t *parent, *gparent, *uncle, *tmp;  //父母p[z]、祖父p[p[z]]、叔叔y、臨時結點*tmp  
  174.    
  175.     while ((parent = node->parent) && parent->color == RED)  
  176.     {     //parent 爲node的父母,且當父母的顏色爲紅時  
  177.         gparent = parent->parent;   //gparent爲祖父  
  178.     
  179.         if (parent == gparent->left)  //當祖父的左孩子即爲父母時。  
  180.                                  //其實上述幾行語句,無非就是理順孩子、父母、祖父的關係。:D。  
  181.         {  
  182.             uncle = gparent->right;  //定義叔叔的概念,叔叔y就是父母的右孩子。  
  183.   
  184.             if (uncle && uncle->color == RED) //情況1:z的叔叔y是紅色的  
  185.             {  
  186.                 uncle->color = BLACK;   //將叔叔結點y着爲黑色  
  187.                 parent->color = BLACK;  //z的父母p[z]也着爲黑色。解決z,p[z]都是紅色的問題。  
  188.                 gparent->color = RED;    
  189.                 node = gparent;     //將祖父當做新增結點z,指針z上移倆層,且着爲紅色。  
  190.             //上述情況1中,只考慮了z作爲父母的右孩子的情況。  
  191.             }  
  192.             else                     //情況2:z的叔叔y是黑色的,  
  193.             {     
  194.                 if (parent->right == node)  //且z爲右孩子  
  195.                 {  
  196.                     root = rb_rotate_left(parent, root); //左旋[結點z,與父母結點]  
  197.                     tmp = parent;  
  198.                     parent = node;  
  199.                     node = tmp;     //parent與node 互換角色  
  200.                 }  
  201.                              //情況3:z的叔叔y是黑色的,此時z成爲了左孩子。  
  202.                                     //注意,1:情況3是由上述情況2變化而來的。  
  203.                                     //......2:z的叔叔總是黑色的,否則就是情況1了。  
  204.                 parent->color = BLACK;   //z的父母p[z]着爲黑色  
  205.                 gparent->color = RED;    //原祖父結點着爲紅色  
  206.                 root = rb_rotate_right(gparent, root); //右旋[結點z,與祖父結點]  
  207.             }  
  208.         }   
  209.    
  210.         else   
  211.         {       
  212.         // if (parent == gparent->right) 當祖父的右孩子即爲父母時。(解釋請看本文評論下第23樓,同時,感謝SupremeHover指正!)  
  213.             uncle = gparent->left;  //祖父的左孩子作爲叔叔結點。[原理還是與上部分一樣的]  
  214.             if (uncle && uncle->color == RED)  //情況1:z的叔叔y是紅色的  
  215.             {  
  216.                 uncle->color = BLACK;  
  217.                 parent->color = BLACK;  
  218.                 gparent->color = RED;  
  219.                 node = gparent;           //同上。  
  220.             }  
  221.             else                               //情況2:z的叔叔y是黑色的,  
  222.             {  
  223.                 if (parent->left == node)  //且z爲左孩子  
  224.                 {  
  225.                     root = rb_rotate_right(parent, root);  //以結點parent、root右旋  
  226.                     tmp = parent;  
  227.                     parent = node;  
  228.                     node = tmp;       //parent與node 互換角色  
  229.                 }   
  230.                   //經過情況2的變化,成爲了情況3.  
  231.                 parent->color = BLACK;  
  232.                 gparent->color = RED;  
  233.                 root = rb_rotate_left(gparent, root);   //以結點gparent和root左旋  
  234.             }  
  235.         }  
  236.     }  
  237.    
  238.     root->color = BLACK; //根結點,不論怎樣,都得置爲黑色。  
  239.     return root;      //返回根結點。  
  240. }  
  241.   
  242.   
  243. //六、紅黑樹的刪除  
  244. //------------------------------------------------------------  
  245. //紅黑樹的刪除結點  
  246. rb_node_t* rb_erase(key_t key, rb_node_t *root)  
  247. {  
  248.     rb_node_t *child, *parent, *old, *left, *node;  
  249.     color_t color;  
  250.    
  251.     if (!(node = rb_search_auxiliary(key, root, NULL)))  //調用rb_search_auxiliary查找要刪除的  
  252.   
  253. 結點  
  254.     {  
  255.         printf("key %d is not exist!/n");  
  256.         return root;  
  257.     }  
  258.    
  259.     old = node;  
  260.    
  261.     if (node->left && node->right)  
  262.     {  
  263.         node = node->right;  
  264.         while ((left = node->left) != NULL)  
  265.         {  
  266.             node = left;  
  267.         }  
  268.         child = node->right;  
  269.         parent = node->parent;  
  270.         color = node->color;  
  271.     
  272.         if (child)  
  273.         {  
  274.             child->parent = parent;  
  275.         }  
  276.         if (parent)  
  277.         {  
  278.             if (parent->left == node)  
  279.             {  
  280.                 parent->left = child;  
  281.             }  
  282.             else  
  283.             {  
  284.                 parent->right = child;  
  285.             }  
  286.         }  
  287.         else  
  288.         {  
  289.             root = child;  
  290.         }  
  291.     
  292.         if (node->parent == old)  
  293.         {  
  294.             parent = node;  
  295.         }  
  296.     
  297.         node->parent = old->parent;  
  298.         node->color = old->color;  
  299.         node->right = old->right;  
  300.         node->left = old->left;  
  301.     
  302.         if (old->parent)  
  303.         {  
  304.             if (old->parent->left == old)  
  305.             {  
  306.                 old->parent->left = node;  
  307.             }  
  308.             else  
  309.             {  
  310.                 old->parent->right = node;  
  311.             }  
  312.         }   
  313.         else  
  314.         {  
  315.             root = node;  
  316.         }  
  317.     
  318.         old->left->parent = node;  
  319.         if (old->right)  
  320.         {  
  321.             old->right->parent = node;  
  322.         }  
  323.     }  
  324.     else  
  325.     {  
  326.         if (!node->left)  
  327.         {  
  328.             child = node->right;  
  329.         }  
  330.         else if (!node->right)  
  331.         {  
  332.             child = node->left;  
  333.         }  
  334.         parent = node->parent;  
  335.         color = node->color;  
  336.     
  337.         if (child)  
  338.         {  
  339.             child->parent = parent;  
  340.         }  
  341.         if (parent)  
  342.         {  
  343.             if (parent->left == node)  
  344.             {  
  345.                 parent->left = child;  
  346.             }  
  347.             else  
  348.             {  
  349.                 parent->right = child;  
  350.             }  
  351.         }  
  352.         else  
  353.         {  
  354.             root = child;  
  355.         }  
  356.     }  
  357.    
  358.     free(old);  
  359.    
  360.     if (color == BLACK)  
  361.     {  
  362.         root = rb_erase_rebalance(child, parent, root); //調用rb_erase_rebalance來恢復紅黑樹性  
  363.   
  364. 質  
  365.     }  
  366.    
  367.     return root;  
  368. }  
  369.   
  370.   
  371. //七、紅黑樹的4種刪除情況  
  372. //----------------------------------------------------------------  
  373. //紅黑樹修復刪除的4種情況  
  374. //爲了表示下述註釋的方便,也爲了讓下述代碼與我的倆篇文章相對應,  
  375. //x表示要刪除的結點,*other、w表示兄弟結點,  
  376. //----------------------------------------------------------------  
  377. static rb_node_t* rb_erase_rebalance(rb_node_t *node, rb_node_t *parent, rb_node_t *root)  
  378. {  
  379.     rb_node_t *other, *o_left, *o_right;   //x的兄弟*other,兄弟左孩子*o_left,*o_right  
  380.    
  381.     while ((!node || node->color == BLACK) && node != root)   
  382.     {  
  383.         if (parent->left == node)  
  384.         {  
  385.             other = parent->right;  
  386.             if (other->color == RED)   //情況1:x的兄弟w是紅色的  
  387.             {  
  388.                 other->color = BLACK;    
  389.                 parent->color = RED;   //上倆行,改變顏色,w->黑、p[x]->紅。  
  390.                 root = rb_rotate_left(parent, root);  //再對p[x]做一次左旋  
  391.                 other = parent->right;  //x的新兄弟new w 是旋轉之前w的某個孩子。其實就是左旋後  
  392.   
  393. 的效果。  
  394.             }  
  395.             if ((!other->left || other->left->color == BLACK) &&  
  396.                 (!other->right || other->right->color == BLACK))    
  397.                           //情況2:x的兄弟w是黑色,且w的倆個孩子也  
  398.   
  399. 都是黑色的  
  400.   
  401.             {                         //由於w和w的倆個孩子都是黑色的,則在x和w上得去掉一黑色,  
  402.                 other->color = RED;   //於是,兄弟w變爲紅色。  
  403.                 node = parent;    //p[x]爲新結點x  
  404.                 parent = node->parent;  //x<-p[x]  
  405.             }  
  406.             else                       //情況3:x的兄弟w是黑色的,  
  407.             {                          //且,w的左孩子是紅色,右孩子爲黑色。  
  408.                 if (!other->right || other->right->color == BLACK)  
  409.                 {  
  410.                     if ((o_left = other->left))   //w和其左孩子left[w],顏色交換。  
  411.                     {  
  412.                         o_left->color = BLACK;    //w的左孩子變爲由黑->紅色  
  413.                     }   
  414.                     other->color = RED;           //w由黑->紅  
  415.                     root = rb_rotate_right(other, root);  //再對w進行右旋,從而紅黑性質恢復。  
  416.                     other = parent->right;        //變化後的,父結點的右孩子,作爲新的兄弟結點  
  417.   
  418. w。  
  419.                 }  
  420.                             //情況4:x的兄弟w是黑色的  
  421.       
  422.                 other->color = parent->color;  //把兄弟節點染成當前節點父節點的顏色。  
  423.                 parent->color = BLACK;  //把當前節點父節點染成黑色  
  424.                 if (other->right)      //且w的右孩子是紅  
  425.                 {  
  426.                     other->right->color = BLACK;  //兄弟節點w右孩子染成黑色  
  427.                 }  
  428.                 root = rb_rotate_left(parent, root);  //並再做一次左旋  
  429.                 node = root;   //並把x置爲根。  
  430.                 break;  
  431.             }  
  432.         }  
  433.         //下述情況與上述情況,原理一致。分析略。  
  434.         else  
  435.         {  
  436.             other = parent->left;  
  437.             if (other->color == RED)  
  438.             {  
  439.                 other->color = BLACK;  
  440.                 parent->color = RED;  
  441.                 root = rb_rotate_right(parent, root);  
  442.                 other = parent->left;  
  443.             }  
  444.             if ((!other->left || other->left->color == BLACK) &&  
  445.                 (!other->right || other->right->color == BLACK))  
  446.             {  
  447.                 other->color = RED;  
  448.                 node = parent;  
  449.                 parent = node->parent;  
  450.             }  
  451.             else  
  452.             {  
  453.                 if (!other->left || other->left->color == BLACK)  
  454.                 {  
  455.                     if ((o_right = other->right))  
  456.                     {  
  457.                         o_right->color = BLACK;  
  458.                     }  
  459.                     other->color = RED;  
  460.                     root = rb_rotate_left(other, root);  
  461.                     other = parent->left;  
  462.                 }  
  463.                 other->color = parent->color;  
  464.                 parent->color = BLACK;  
  465.                 if (other->left)  
  466.                 {  
  467.                     other->left->color = BLACK;  
  468.                 }  
  469.                 root = rb_rotate_right(parent, root);  
  470.                 node = root;  
  471.                 break;  
  472.             }  
  473.         }  
  474.     }  
  475.    
  476.     if (node)  
  477.     {  
  478.         node->color = BLACK;  //最後將node[上述步驟置爲了根結點],改爲黑色。  
  479.     }    
  480.     return root;  //返回root  
  481. }  
  482.   
  483.   
  484. //八、測試用例  
  485. //主函數  
  486. int main()  
  487. {  
  488.     int i, count = 100;  
  489.     key_t key;  
  490.     rb_node_t* root = NULL, *node = NULL;  
  491.       
  492.     srand(time(NULL));  
  493.     for (i = 1; i < count; ++i)  
  494.     {  
  495.         key = rand() % count;  
  496.         if ((root = rb_insert(key, i, root)))  
  497.         {  
  498.             printf("[i = %d] insert key %d success!/n", i, key);  
  499.         }  
  500.         else  
  501.         {  
  502.             printf("[i = %d] insert key %d error!/n", i, key);  
  503.             exit(-1);  
  504.         }  
  505.     
  506.         if ((node = rb_search(key, root)))  
  507.         {  
  508.             printf("[i = %d] search key %d success!/n", i, key);  
  509.         }  
  510.         else  
  511.         {  
  512.             printf("[i = %d] search key %d error!/n", i, key);  
  513.             exit(-1);  
  514.         }  
  515.         if (!(i % 10))  
  516.         {  
  517.             if ((root = rb_erase(key, root)))  
  518.             {  
  519.                 printf("[i = %d] erase key %d success/n", i, key);  
  520.             }  
  521.             else  
  522.             {  
  523.                 printf("[i = %d] erase key %d error/n", i, key);  
  524.             }  
  525.         }  
  526.     }  
  527.    
  528.     return 0;  
  529. }  

ok,完。

後記:

一、歡迎任何人就此份源碼,以及我的前述倆篇文章,進行討論、提議。
但任何人,引用此份源碼剖析,必須得註明作者本人July以及出處。
紅黑樹系列,已經寫了三篇文章,相信,教你透徹瞭解紅黑樹的目的,應該達到了。
二、本文完整源碼,請到此處下載:

http://download.csdn.net/source/2958890

1、教你透徹瞭解紅黑樹
2、紅黑樹算法的實現與剖析
3、紅黑樹的c源碼實現與剖析
4、一步一圖一代碼,R-B Tree
5、紅黑樹插入和刪除結點的全程演示
6、紅黑樹的c++完整實現源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章