zoukankan      html  css  js  c++  java
  • 手写C语言红黑树

    主要实现如下功能

    1.红黑树的前中后顺遍历

    2.红黑树的创建

    3.红黑树的销毁

    4.查找"红黑树"中键值为key的节点(递归)

    5.查找"红黑树"中键值为key的节点(非递归)

    6.返回最小结点的值(将值保存到val中)

    7.返回最大结点的值(将值保存到val中)

    8.打印红黑树

    9.将结点插入到红黑树中

    10.删除结点

    头文件

     1 #ifndef _RBTREE_H_
     2 #define _RBTREE_H_
     3 
     4 #define RED        0    // 红色节点
     5 #define BLACK    1    // 黑色节点
     6 
     7 typedef int Type;
     8 
     9 // 红黑树的节点
    10 typedef struct RBTreeNode {
    11     unsigned char color;        // 颜色(RED 或 BLACK)
    12     Type   key;                    // 关键字(键值)
    13     struct RBTreeNode* left;    // 左孩子
    14     struct RBTreeNode* right;    // 右孩子
    15     struct RBTreeNode* parent;    // 父结点
    16 }Node, * RBTree;
    17 
    18 // 红黑树的根
    19 typedef struct rb_root {
    20     Node* node;
    21 }RBRoot;
    22 
    23 // 创建红黑树,返回"红黑树的根"
    24 RBRoot* create_rbtree();
    25 
    26 // 将结点插入到红黑树中。插入成功,返回0;失败返回-1。
    27 int insert_rbtree(RBRoot* root, Type key);
    28 
    29 // 删除结点(key为节点的值)
    30 void delete_rbtree(RBRoot* root, Type key);
    31 
    32 
    33 // 前序遍历"红黑树"
    34 void preorder_rbtree(RBRoot* root);
    35 // 中序遍历"红黑树"
    36 void inorder_rbtree(RBRoot* root);
    37 // 后序遍历"红黑树"
    38 void postorder_rbtree(RBRoot* root);
    39 
    40 // 销毁红黑树
    41 void destroy_rbtree(RBRoot* root);
    42 
    43 // (递归实现)查找"红黑树"中键值为key的节点。找到的话,返回0;否则,返回-1。
    44 int rbtree_search(RBRoot* root, Type key);
    45 // (非递归实现)查找"红黑树"中键值为key的节点。找到的话,返回0;否则,返回-1。
    46 int iterative_rbtree_search(RBRoot* root, Type key);
    47 
    48 // 返回最小结点的值(将值保存到val中)。找到的话,返回0;否则返回-1。
    49 int rbtree_minimum(RBRoot* root, int* val);
    50 // 返回最大结点的值(将值保存到val中)。找到的话,返回0;否则返回-1。
    51 int rbtree_maximum(RBRoot* root, int* val);
    52 
    53 // 打印红黑树
    54 void print_rbtree(RBRoot* root);
    55 
    56 #endif
    rbtree.h

    头文件实现

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include "rbtree.h"
      4 
      5 #define rb_parent(r)   ((r)->parent)
      6 #define rb_color(r) ((r)->color)
      7 #define rb_is_red(r)   ((r)->color==RED)
      8 #define rb_is_black(r)  ((r)->color==BLACK)
      9 #define rb_set_black(r)  do { (r)->color = BLACK; } while (0)
     10 #define rb_set_red(r)  do { (r)->color = RED; } while (0)
     11 #define rb_set_parent(r,p)  do { (r)->parent = (p); } while (0)
     12 #define rb_set_color(r,c)  do { (r)->color = (c); } while (0)
     13 
     14 /*
     15  * 创建红黑树,返回"红黑树的根"!
     16  */
     17 RBRoot* create_rbtree()
     18 {
     19     RBRoot* root = (RBRoot*)malloc(sizeof(RBRoot));
     20     root->node = NULL;
     21 
     22     return root;
     23 }
     24 
     25 /*
     26  * 前序遍历"红黑树"
     27  */
     28 static void preorder(RBTree tree)
     29 {
     30     if (tree != NULL)
     31     {
     32         printf("%d ", tree->key);
     33         preorder(tree->left);
     34         preorder(tree->right);
     35     }
     36 }
     37 void preorder_rbtree(RBRoot* root)
     38 {
     39     if (root)
     40         preorder(root->node);
     41 }
     42 
     43 /*
     44  * 中序遍历"红黑树"
     45  */
     46 static void inorder(RBTree tree)
     47 {
     48     if (tree != NULL)
     49     {
     50         inorder(tree->left);
     51         printf("%d ", tree->key);
     52         inorder(tree->right);
     53     }
     54 }
     55 
     56 void inorder_rbtree(RBRoot* root)
     57 {
     58     if (root)
     59         inorder(root->node);
     60 }
     61 
     62 /*
     63  * 后序遍历"红黑树"
     64  */
     65 static void postorder(RBTree tree)
     66 {
     67     if (tree != NULL)
     68     {
     69         postorder(tree->left);
     70         postorder(tree->right);
     71         printf("%d ", tree->key);
     72     }
     73 }
     74 
     75 void postorder_rbtree(RBRoot* root)
     76 {
     77     if (root)
     78         postorder(root->node);
     79 }
     80 
     81 /*
     82  * (递归实现)查找"红黑树x"中键值为key的节点
     83  */
     84 static Node* search(RBTree x, Type key)
     85 {
     86     if (x == NULL || x->key == key)
     87         return x;
     88 
     89     if (key < x->key)
     90         return search(x->left, key);
     91     else
     92         return search(x->right, key);
     93 }
     94 
     95 int rbtree_search(RBRoot* root, Type key)
     96 {
     97     if (root)
     98         return search(root->node, key) ? 0 : -1;
     99 }
    100 
    101 /*
    102  * (非递归实现)查找"红黑树x"中键值为key的节点
    103  */
    104 static Node* iterative_search(RBTree x, Type key)
    105 {
    106     while ((x != NULL) && (x->key != key))
    107     {
    108         if (key < x->key)
    109             x = x->left;
    110         else
    111             x = x->right;
    112     }
    113 
    114     return x;
    115 }
    116 
    117 int iterative_rbtree_search(RBRoot* root, Type key)
    118 {
    119     if (root)
    120         return iterative_search(root->node, key) ? 0 : -1;
    121 }
    122 
    123 /*
    124  * 查找最小结点(非递归):返回tree为根结点的红黑树的左子树叶结点。
    125  */
    126 static Node* minimum(RBTree tree)
    127 {
    128     if (tree == NULL)
    129         return NULL;
    130 
    131     while (tree->left != NULL)
    132         tree = tree->left;
    133     return tree;
    134 }
    135 
    136 int rbtree_minimum(RBRoot* root, int* val)
    137 {
    138     Node* node = NULL;
    139 
    140     if (root)
    141         node = minimum(root->node);
    142 
    143     if (node == NULL)
    144         return -1;
    145 
    146     *val = node->key;
    147     return 0;
    148 }
    149 
    150 /*
    151  * 查找最大结点:返回tree为根结点的红黑树的右子树最大结点。
    152  */
    153 static Node* maximum(RBTree tree)
    154 {
    155     if (tree == NULL)
    156         return NULL;
    157 
    158     while (tree->right != NULL)
    159         tree = tree->right;
    160     return tree;
    161 }
    162 
    163 int rbtree_maximum(RBRoot* root, int* val)
    164 {
    165     Node* node = NULL;
    166 
    167     if (root)
    168         node = maximum(root->node);
    169 
    170     if (node == NULL)
    171         return -1;
    172 
    173     *val = node->key;
    174     return 0;
    175 }
    176 
    177 /*
    178  * 找结点(x)的后继结点。即,查找"红黑树中数据值大于该结点"的"最小结点"。
    179  */
    180 static Node* rbtree_successor(RBTree x)
    181 {
    182     // 如果x存在右孩子,则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。
    183     if (x->right != NULL)
    184         return minimum(x->right);
    185 
    186     // 如果x没有右孩子。则x有以下两种可能:
    187     // (01) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。
    188     // (02) x是"一个右孩子",则查找"x的最低的父结点,并且该父结点要具有左孩子",找到的这个"最低的父结点"就是"x的后继结点"。
    189     Node* y = x->parent;
    190     while ((y != NULL) && (x == y->right))
    191     {
    192         x = y;
    193         y = y->parent;
    194     }
    195 
    196     return y;
    197 }
    198 
    199 /*
    200  * 找结点(x)的前驱结点。即,查找"红黑树中数据值小于该结点"的"最大结点"。
    201  */
    202 static Node* rbtree_predecessor(RBTree x)
    203 {
    204     // 如果x存在左孩子,则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。
    205     if (x->left != NULL)
    206         return maximum(x->left);
    207 
    208     // 如果x没有左孩子。则x有以下两种可能:
    209     // (01) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。
    210     // (01) x是"一个左孩子",则查找"x的最低的父结点,并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"。
    211     Node* y = x->parent;
    212     while ((y != NULL) && (x == y->left))
    213     {
    214         x = y;
    215         y = y->parent;
    216     }
    217 
    218     return y;
    219 }
    220 
    221 /*
    222  * 对红黑树的节点(x)进行左旋转
    223  *
    224  * 左旋示意图(对节点x进行左旋):
    225  *      px                              px
    226  *     /                               /
    227  *    x                               y
    228  *   /  \      --(左旋)-->           / \                #
    229  *  lx   y                          x  ry
    230  *     /   \                       /  \
    231  *    ly   ry                     lx  ly
    232  *
    233  *
    234  */
    235 static void rbtree_left_rotate(RBRoot* root, Node* x)
    236 {
    237     // 设置x的右孩子为y
    238     Node* y = x->right;
    239 
    240     // 将 “y的左孩子” 设为 “x的右孩子”;
    241     // 如果y的左孩子非空,将 “x” 设为 “y的左孩子的父亲”
    242     x->right = y->left;
    243     if (y->left != NULL)
    244         y->left->parent = x;
    245 
    246     // 将 “x的父亲” 设为 “y的父亲”
    247     y->parent = x->parent;
    248 
    249     if (x->parent == NULL)
    250     {
    251         root->node = y;            // 如果 “x的父亲” 是空节点,则将y设为根节点
    252     }
    253     else
    254     {
    255         if (x->parent->left == x)
    256             x->parent->left = y;    // 如果 x是它父节点的左孩子,则将y设为“x的父节点的左孩子”
    257         else
    258             x->parent->right = y;    // 如果 x是它父节点的左孩子,则将y设为“x的父节点的左孩子”
    259     }
    260 
    261     // 将 “x” 设为 “y的左孩子”
    262     y->left = x;
    263     // 将 “x的父节点” 设为 “y”
    264     x->parent = y;
    265 }
    266 
    267 /*
    268  * 对红黑树的节点(y)进行右旋转
    269  *
    270  * 右旋示意图(对节点y进行左旋):
    271  *            py                               py
    272  *           /                                /
    273  *          y                                x
    274  *         /  \      --(右旋)-->            /  \                     #
    275  *        x   ry                           lx   y
    276  *       / \                                   / \                   #
    277  *      lx  rx                                rx  ry
    278  *
    279  */
    280 static void rbtree_right_rotate(RBRoot* root, Node* y)
    281 {
    282     // 设置x是当前节点的左孩子。
    283     Node* x = y->left;
    284 
    285     // 将 “x的右孩子” 设为 “y的左孩子”;
    286     // 如果"x的右孩子"不为空的话,将 “y” 设为 “x的右孩子的父亲”
    287     y->left = x->right;
    288     if (x->right != NULL)
    289         x->right->parent = y;
    290 
    291     // 将 “y的父亲” 设为 “x的父亲”
    292     x->parent = y->parent;
    293 
    294     if (y->parent == NULL)
    295     {
    296         //tree = x;            // 如果 “y的父亲” 是空节点,则将x设为根节点
    297         root->node = x;            // 如果 “y的父亲” 是空节点,则将x设为根节点
    298     }
    299     else
    300     {
    301         if (y == y->parent->right)
    302             y->parent->right = x;    // 如果 y是它父节点的右孩子,则将x设为“y的父节点的右孩子”
    303         else
    304             y->parent->left = x;    // (y是它父节点的左孩子) 将x设为“x的父节点的左孩子”
    305     }
    306 
    307     // 将 “y” 设为 “x的右孩子”
    308     x->right = y;
    309 
    310     // 将 “y的父节点” 设为 “x”
    311     y->parent = x;
    312 }
    313 
    314 /*
    315  * 红黑树插入修正函数
    316  *
    317  * 在向红黑树中插入节点之后(失去平衡),再调用该函数;
    318  * 目的是将它重新塑造成一颗红黑树。
    319  *
    320  * 参数说明:
    321  *     root 红黑树的根
    322  *     node 插入的结点
    323  */
    324 static void rbtree_insert_fixup(RBRoot* root, Node* node)
    325 {
    326     Node* parent, * gparent;
    327 
    328     // 若“父节点存在,并且父节点的颜色是红色”
    329     while ((parent = rb_parent(node)) && rb_is_red(parent))
    330     {
    331         gparent = rb_parent(parent);
    332 
    333         //若“父节点”是“祖父节点的左孩子”
    334         if (parent == gparent->left)
    335         {
    336             // Case 1条件:叔叔节点是红色
    337             {
    338                 Node* uncle = gparent->right;
    339                 if (uncle && rb_is_red(uncle))
    340                 {
    341                     rb_set_black(uncle);
    342                     rb_set_black(parent);
    343                     rb_set_red(gparent);
    344                     node = gparent;
    345                     continue;
    346                 }
    347             }
    348 
    349             // Case 2条件:叔叔是黑色,且当前节点是右孩子
    350             if (parent->right == node)
    351             {
    352                 Node* tmp;
    353                 rbtree_left_rotate(root, parent);
    354                 tmp = parent;
    355                 parent = node;
    356                 node = tmp;
    357             }
    358 
    359             // Case 3条件:叔叔是黑色,且当前节点是左孩子。
    360             rb_set_black(parent);
    361             rb_set_red(gparent);
    362             rbtree_right_rotate(root, gparent);
    363         }
    364         else//若“z的父节点”是“z的祖父节点的右孩子”
    365         {
    366             // Case 1条件:叔叔节点是红色
    367             {
    368                 Node* uncle = gparent->left;
    369                 if (uncle && rb_is_red(uncle))
    370                 {
    371                     rb_set_black(uncle);
    372                     rb_set_black(parent);
    373                     rb_set_red(gparent);
    374                     node = gparent;
    375                     continue;
    376                 }
    377             }
    378 
    379             // Case 2条件:叔叔是黑色,且当前节点是左孩子
    380             if (parent->left == node)
    381             {
    382                 Node* tmp;
    383                 rbtree_right_rotate(root, parent);
    384                 tmp = parent;
    385                 parent = node;
    386                 node = tmp;
    387             }
    388 
    389             // Case 3条件:叔叔是黑色,且当前节点是右孩子。
    390             rb_set_black(parent);
    391             rb_set_red(gparent);
    392             rbtree_left_rotate(root, gparent);
    393         }
    394     }
    395 
    396     // 将根节点设为黑色
    397     rb_set_black(root->node);
    398 }
    399 
    400 /*
    401  * 添加节点:将节点(node)插入到红黑树中
    402  *
    403  * 参数说明:
    404  *     root 红黑树的根
    405  *     node 插入的结点        // 对应《算法导论》中的z
    406  */
    407 static void rbtree_insert(RBRoot* root, Node* node)
    408 {
    409     Node* y = NULL;
    410     Node* x = root->node;
    411 
    412     // 1. 将红黑树当作一颗二叉查找树,将节点添加到二叉查找树中。
    413     while (x != NULL)
    414     {
    415         y = x;
    416         if (node->key < x->key)
    417             x = x->left;
    418         else
    419             x = x->right;
    420     }
    421     rb_parent(node) = y;
    422 
    423     if (y != NULL)
    424     {
    425         if (node->key < y->key)
    426             y->left = node;                // 情况2:若“node所包含的值” < “y所包含的值”,则将node设为“y的左孩子”
    427         else
    428             y->right = node;            // 情况3:(“node所包含的值” >= “y所包含的值”)将node设为“y的右孩子” 
    429     }
    430     else
    431     {
    432         root->node = node;                // 情况1:若y是空节点,则将node设为根
    433     }
    434 
    435     // 2. 设置节点的颜色为红色
    436     node->color = RED;
    437 
    438     // 3. 将它重新修正为一颗二叉查找树
    439     rbtree_insert_fixup(root, node);
    440 }
    441 
    442 /*
    443  * 创建结点
    444  *
    445  * 参数说明:
    446  *     key 是键值。
    447  *     parent 是父结点。
    448  *     left 是左孩子。
    449  *     right 是右孩子。
    450  */
    451 static Node* create_rbtree_node(Type key, Node* parent, Node* left, Node* right)
    452 {
    453     Node* p;
    454 
    455     if ((p = (Node*)malloc(sizeof(Node))) == NULL)
    456         return NULL;
    457     p->key = key;
    458     p->left = left;
    459     p->right = right;
    460     p->parent = parent;
    461     p->color = BLACK; // 默认为黑色
    462 
    463     return p;
    464 }
    465 
    466 /*
    467  * 新建结点(节点键值为key),并将其插入到红黑树中
    468  *
    469  * 参数说明:
    470  *     root 红黑树的根
    471  *     key 插入结点的键值
    472  * 返回值:
    473  *     0,插入成功
    474  *     -1,插入失败
    475  */
    476 int insert_rbtree(RBRoot* root, Type key)
    477 {
    478     Node* node;    // 新建结点
    479 
    480     // 不允许插入相同键值的节点。
    481     // (若想允许插入相同键值的节点,注释掉下面两句话即可!)
    482     if (search(root->node, key) != NULL)
    483         return -1;
    484 
    485     // 如果新建结点失败,则返回。
    486     if ((node = create_rbtree_node(key, NULL, NULL, NULL)) == NULL)
    487         return -1;
    488 
    489     rbtree_insert(root, node);
    490 
    491     return 0;
    492 }
    493 
    494 /*
    495  * 红黑树删除修正函数
    496  *
    497  * 在从红黑树中删除插入节点之后(红黑树失去平衡),再调用该函数;
    498  * 目的是将它重新塑造成一颗红黑树。
    499  *
    500  * 参数说明:
    501  *     root 红黑树的根
    502  *     node 待修正的节点
    503  */
    504 static void rbtree_delete_fixup(RBRoot* root, Node* node, Node* parent)
    505 {
    506     Node* other;
    507 
    508     while ((!node || rb_is_black(node)) && node != root->node)
    509     {
    510         if (parent->left == node)
    511         {
    512             other = parent->right;
    513             if (rb_is_red(other))
    514             {
    515                 // Case 1: x的兄弟w是红色的  
    516                 rb_set_black(other);
    517                 rb_set_red(parent);
    518                 rbtree_left_rotate(root, parent);
    519                 other = parent->right;
    520             }
    521             if ((!other->left || rb_is_black(other->left)) &&
    522                 (!other->right || rb_is_black(other->right)))
    523             {
    524                 // Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的  
    525                 rb_set_red(other);
    526                 node = parent;
    527                 parent = rb_parent(node);
    528             }
    529             else
    530             {
    531                 if (!other->right || rb_is_black(other->right))
    532                 {
    533                     // Case 3: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。  
    534                     rb_set_black(other->left);
    535                     rb_set_red(other);
    536                     rbtree_right_rotate(root, other);
    537                     other = parent->right;
    538                 }
    539                 // Case 4: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
    540                 rb_set_color(other, rb_color(parent));
    541                 rb_set_black(parent);
    542                 rb_set_black(other->right);
    543                 rbtree_left_rotate(root, parent);
    544                 node = root->node;
    545                 break;
    546             }
    547         }
    548         else
    549         {
    550             other = parent->left;
    551             if (rb_is_red(other))
    552             {
    553                 // Case 1: x的兄弟w是红色的  
    554                 rb_set_black(other);
    555                 rb_set_red(parent);
    556                 rbtree_right_rotate(root, parent);
    557                 other = parent->left;
    558             }
    559             if ((!other->left || rb_is_black(other->left)) &&
    560                 (!other->right || rb_is_black(other->right)))
    561             {
    562                 // Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的  
    563                 rb_set_red(other);
    564                 node = parent;
    565                 parent = rb_parent(node);
    566             }
    567             else
    568             {
    569                 if (!other->left || rb_is_black(other->left))
    570                 {
    571                     // Case 3: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。  
    572                     rb_set_black(other->right);
    573                     rb_set_red(other);
    574                     rbtree_left_rotate(root, other);
    575                     other = parent->left;
    576                 }
    577                 // Case 4: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
    578                 rb_set_color(other, rb_color(parent));
    579                 rb_set_black(parent);
    580                 rb_set_black(other->left);
    581                 rbtree_right_rotate(root, parent);
    582                 node = root->node;
    583                 break;
    584             }
    585         }
    586     }
    587     if (node)
    588         rb_set_black(node);
    589 }
    590 
    591 /*
    592  * 删除结点
    593  *
    594  * 参数说明:
    595  *     tree 红黑树的根结点
    596  *     node 删除的结点
    597  */
    598 void rbtree_delete(RBRoot* root, Node* node)
    599 {
    600     Node* child, * parent;
    601     int color;
    602 
    603     // 被删除节点的"左右孩子都不为空"的情况。
    604     if ((node->left != NULL) && (node->right != NULL))
    605     {
    606         // 被删节点的后继节点。(称为"取代节点")
    607         // 用它来取代"被删节点"的位置,然后再将"被删节点"去掉。
    608         Node* replace = node;
    609 
    610         // 获取后继节点
    611         replace = replace->right;
    612         while (replace->left != NULL)
    613             replace = replace->left;
    614 
    615         // "node节点"不是根节点(只有根节点不存在父节点)
    616         if (rb_parent(node))
    617         {
    618             if (rb_parent(node)->left == node)
    619                 rb_parent(node)->left = replace;
    620             else
    621                 rb_parent(node)->right = replace;
    622         }
    623         else
    624             // "node节点"是根节点,更新根节点。
    625             root->node = replace;
    626 
    627         // child是"取代节点"的右孩子,也是需要"调整的节点"。
    628         // "取代节点"肯定不存在左孩子!因为它是一个后继节点。
    629         child = replace->right;
    630         parent = rb_parent(replace);
    631         // 保存"取代节点"的颜色
    632         color = rb_color(replace);
    633 
    634         // "被删除节点"是"它的后继节点的父节点"
    635         if (parent == node)
    636         {
    637             parent = replace;
    638         }
    639         else
    640         {
    641             // child不为空
    642             if (child)
    643                 rb_set_parent(child, parent);
    644             parent->left = child;
    645 
    646             replace->right = node->right;
    647             rb_set_parent(node->right, replace);
    648         }
    649 
    650         replace->parent = node->parent;
    651         replace->color = node->color;
    652         replace->left = node->left;
    653         node->left->parent = replace;
    654 
    655         if (color == BLACK)
    656             rbtree_delete_fixup(root, child, parent);
    657         free(node);
    658 
    659         return;
    660     }
    661 
    662     if (node->left != NULL)
    663         child = node->left;
    664     else
    665         child = node->right;
    666 
    667     parent = node->parent;
    668     // 保存"取代节点"的颜色
    669     color = node->color;
    670 
    671     if (child)
    672         child->parent = parent;
    673 
    674     // "node节点"不是根节点
    675     if (parent)
    676     {
    677         if (parent->left == node)
    678             parent->left = child;
    679         else
    680             parent->right = child;
    681     }
    682     else
    683         root->node = child;
    684 
    685     if (color == BLACK)
    686         rbtree_delete_fixup(root, child, parent);
    687     free(node);
    688 }
    689 
    690 /*
    691  * 删除键值为key的结点
    692  *
    693  * 参数说明:
    694  *     tree 红黑树的根结点
    695  *     key 键值
    696  */
    697 void delete_rbtree(RBRoot* root, Type key)
    698 {
    699     Node* z, * node;
    700 
    701     if ((z = search(root->node, key)) != NULL)
    702         rbtree_delete(root, z);
    703 }
    704 
    705 /*
    706  * 销毁红黑树
    707  */
    708 static void rbtree_destroy(RBTree tree)
    709 {
    710     if (tree == NULL)
    711         return;
    712 
    713     if (tree->left != NULL)
    714         rbtree_destroy(tree->left);
    715     if (tree->right != NULL)
    716         rbtree_destroy(tree->right);
    717 
    718     free(tree);
    719 }
    720 
    721 void destroy_rbtree(RBRoot* root)
    722 {
    723     if (root != NULL)
    724         rbtree_destroy(root->node);
    725 
    726     free(root);
    727 }
    728 
    729 /*
    730  * 打印"红黑树"
    731  *
    732  * tree       -- 红黑树的节点
    733  * key        -- 节点的键值
    734  * direction  --  0,表示该节点是根节点;
    735  *               -1,表示该节点是它的父结点的左孩子;
    736  *                1,表示该节点是它的父结点的右孩子。
    737  */
    738 static void rbtree_print(RBTree tree, Type key, int direction)
    739 {
    740     if (tree != NULL)
    741     {
    742         if (direction == 0)    // tree是根节点
    743             printf("%2d(B) is root\n", tree->key);
    744         else                // tree是分支节点
    745             printf("%2d(%s) is %2d's %6s child\n", tree->key, rb_is_red(tree) ? "R" : "B", key, direction == 1 ? "right" : "left");
    746 
    747         rbtree_print(tree->left, tree->key, -1);
    748         rbtree_print(tree->right, tree->key, 1);
    749     }
    750 }
    751 
    752 void print_rbtree(RBRoot* root)
    753 {
    754     if (root != NULL && root->node != NULL)
    755         rbtree_print(root->node, root->node->key, 0);
    756 }
    rbtree.cpp

    测试程序

     1 #include <stdio.h>
     2 #include <iostream>
     3 
     4 #include "rbtree.h"
     5 
     6 #define CHECK_INSERT 1    // "插入"动作的检测开关(0,关闭;1,打开)
     7 #define CHECK_DELETE 0    // "删除"动作的检测开关(0,关闭;1,打开)
     8 #define LENGTH(a) ( (sizeof(a)) / (sizeof(a[0])) )
     9 
    10 int main()
    11 {
    12     int a[] = { 10, 40, 30, 60, 90, 70, 20, 50, 80 };
    13     int i, ilen = LENGTH(a);
    14     RBRoot* root = NULL;
    15 
    16     root = create_rbtree();
    17     printf("== 原始数据: ");
    18     for (i = 0; i < ilen; i++)
    19         printf("%d ", a[i]);
    20     printf("\n");
    21 
    22     for (i = 0; i < ilen; i++)
    23     {
    24         insert_rbtree(root, a[i]);
    25 #if CHECK_INSERT
    26         printf("== 添加节点: %d\n", a[i]);
    27         printf("== 树的详细信息: \n");
    28         print_rbtree(root);
    29         printf("\n");
    30 #endif
    31     }
    32 
    33     printf("== 前序遍历: ");
    34     preorder_rbtree(root);
    35 
    36     printf("\n== 中序遍历: ");
    37     inorder_rbtree(root);
    38 
    39     printf("\n== 后序遍历: ");
    40     postorder_rbtree(root);
    41     printf("\n");
    42 
    43     if (rbtree_minimum(root, &i) == 0)
    44         printf("== 最小值: %d\n", i);
    45     if (rbtree_maximum(root, &i) == 0)
    46         printf("== 最大值: %d\n", i);
    47     printf("== 树的详细信息: \n");
    48     print_rbtree(root);
    49     printf("\n");
    50 
    51 #if CHECK_DELETE
    52     for (i = 0; i < ilen; i++)
    53     {
    54         delete_rbtree(root, a[i]);
    55 
    56         printf("== 删除节点: %d\n", a[i]);
    57         if (root)
    58         {
    59             printf("== 树的详细信息: \n");
    60             print_rbtree(root);
    61             printf("\n");
    62         }
    63     }
    64 #endif
    65 
    66     destroy_rbtree(root);
    67 
    68 
    69     system("pause");
    70     return 0;
    71 
    72 }
    main.cpp
  • 相关阅读:
    Thinkphp的 is null 查询条件是什么,以及exp表达式如何使用
    thinkphp5多文件上传如何实现
    如何动态改变audio的播放的src
    js插件---10个免费开源的JS音乐播放器插件
    html5页面怎么播放音频和视频
    Thinkphp5图片上传正常,音频和视频上传失败的原因及解决
    leetcode
    HTML5 画一张图
    Linux内核和根文件系统引导加载程序
    [dp] hdu 4472 Count
  • 原文地址:https://www.cnblogs.com/still-smile/p/15525028.html
Copyright © 2011-2022 走看看