红黑树C实现

  1. // red-black tree
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdarg.h>
  6. #include <time.h>
  7. //
  8. // supplied by user //
  9. //
  10. typedef int KeyType;            // type of key
  11. typedef struct {                // value related to key
  12.     int stuff;
  13. } ValType;
  14. // how to compare keys
  15. #define compLT(a,b) (a < b)
  16. #define compEQ(a,b) (a == b)
  17. /
  18. // implementation independent code //
  19. /
  20. typedef enum {
  21.     RBT_STATUS_OK,
  22.     RBT_STATUS_MEM_EXHAUSTED,
  23.     RBT_STATUS_DUPLICATE_KEY,
  24.     RBT_STATUS_KEY_NOT_FOUND
  25. } RbtStatus;
  26. typedef enum { BLACK, RED } nodeColor;
  27. typedef struct NodeTag {
  28.     struct NodeTag *left;       // left child
  29.     struct NodeTag *right;      // right child
  30.     struct NodeTag *parent;     // parent
  31.     nodeColor color;            // node color (BLACK, RED)
  32.     KeyType key;                // key used for searching
  33.     ValType val;                // data related to key
  34. } NodeType;
  35. #define SENTINEL &sentinel      // all leafs are sentinels(哨兵)
  36. static NodeType sentinel = { SENTINEL, SENTINEL, 0, BLACK, 0};
  37. static NodeType *root = SENTINEL; // root of red-black tree
  38. static void rotateLeft(NodeType *x) {
  39.     // rotate node x to left
  40.     NodeType *y = x->right;
  41.     // establish x->right link
  42.     x->right = y->left;
  43.     if (y->left != SENTINEL) y->left->parent = x;
  44.     // establish y->parent link
  45.     if (y != SENTINEL) y->parent = x->parent;
  46.     if (x->parent) {
  47.         if (x == x->parent->left)
  48.             x->parent->left = y;
  49.         else
  50.             x->parent->right = y;
  51.     } else {
  52.         root = y;
  53.     }
  54.     // link x and y
  55.     y->left = x;
  56.     if (x != SENTINEL) x->parent = y;
  57. }
  58. static void rotateRight(NodeType *x) {
  59.     // rotate node x to right
  60.     NodeType *y = x->left;
  61.     // establish x->left link
  62.     x->left = y->right;
  63.     if (y->right != SENTINEL) y->right->parent = x;
  64.     // establish y->parent link
  65.     if (y != SENTINEL) y->parent = x->parent;
  66.     if (x->parent) {
  67.         if (x == x->parent->right)
  68.             x->parent->right = y;
  69.         else
  70.             x->parent->left = y;
  71.     } else {
  72.         root = y;
  73.     }
  74.     // link x and y
  75.     y->right = x;
  76.     if (x != SENTINEL) x->parent = y;
  77. }
  78. static void insertFixup(NodeType *x) {
  79.     // maintain red-black tree balance
  80.     // after inserting node x
  81.     // check red-black properties
  82.     while (x != root && x->parent->color == RED) {
  83.         // we have a violation
  84.         if (x->parent == x->parent->parent->left) {
  85.             NodeType *y = x->parent->parent->right;
  86.             if (y->color == RED) {
  87.                 // uncle is RED
  88.                 x->parent->color = BLACK;
  89.                 y->color = BLACK;
  90.                 x->parent->parent->color = RED;
  91.                 x = x->parent->parent;
  92.             } else {
  93.                 // uncle is BLACK
  94.                 if (x == x->parent->right) {
  95.                     // make x a left child
  96.                     x = x->parent;
  97.                     rotateLeft(x);
  98.                 }
  99.                 // recolor and rotate
  100.                 x->parent->color = BLACK;
  101.                 x->parent->parent->color = RED;
  102.                 rotateRight(x->parent->parent);
  103.             }
  104.         } else {
  105.             // mirror image of above code
  106.             NodeType *y = x->parent->parent->left;
  107.             if (y->color == RED) {
  108.                 // uncle is RED
  109.                 x->parent->color = BLACK;
  110.                 y->color = BLACK;
  111.                 x->parent->parent->color = RED;
  112.                 x = x->parent->parent;
  113.             } else {
  114.                 // uncle is BLACK
  115.                 if (x == x->parent->left) {
  116.                     x = x->parent;
  117.                     rotateRight(x);
  118.                 }
  119.                 x->parent->color = BLACK;
  120.                 x->parent->parent->color = RED;
  121.                 rotateLeft(x->parent->parent);
  122.             }
  123.         }
  124.     }
  125.     root->color = BLACK;
  126. }
  127. // insert new node (no duplicates allowed)
  128. RbtStatus rbtInsert(KeyType key, ValType val) {
  129.     NodeType *current, *parent, *x;
  130.     // allocate node for data and insert in tree
  131.     // find future parent
  132.     current = root;
  133.     parent = 0;
  134.     while (current != SENTINEL) {
  135.         if (compEQ(key, current->key)) 
  136.             return RBT_STATUS_DUPLICATE_KEY;
  137.         parent = current;
  138.         current = compLT(key, current->key) ?
  139.             current->left : current->right;
  140.     }
  141.     // setup new node
  142.     if ((x = malloc (sizeof(*x))) == 0)
  143.         return RBT_STATUS_MEM_EXHAUSTED;
  144.     x->parent = parent;
  145.     x->left = SENTINEL;
  146.     x->right = SENTINEL;
  147.     x->color = RED;
  148.     x->key = key;
  149.     x->val = val;
  150.     // insert node in tree
  151.     if(parent) {
  152.         if(compLT(key, parent->key))
  153.             parent->left = x;
  154.         else
  155.             parent->right = x;
  156.     } else {
  157.         root = x;
  158.     }
  159.     insertFixup(x);
  160.     return RBT_STATUS_OK;
  161. }
  162. static void deleteFixup(NodeType *x) {
  163.     // maintain red-black tree balance
  164.     // after deleting node x
  165.     while (x != root && x->color == BLACK) {
  166.         if (x == x->parent->left) {
  167.             NodeType *w = x->parent->right;
  168.             if (w->color == RED) {
  169.                 w->color = BLACK;
  170.                 x->parent->color = RED;
  171.                 rotateLeft (x->parent);
  172.                 w = x->parent->right;
  173.             }
  174.             if (w->left->color == BLACK && w->right->color == BLACK) {
  175.                 w->color = RED;
  176.                 x = x->parent;
  177.             } else {
  178.                 if (w->right->color == BLACK) {
  179.                     w->left->color = BLACK;
  180.                     w->color = RED;
  181.                     rotateRight (w);
  182.                     w = x->parent->right;
  183.                 }
  184.                 w->color = x->parent->color;
  185.                 x->parent->color = BLACK;
  186.                 w->right->color = BLACK;
  187.                 rotateLeft (x->parent);
  188.                 x = root;
  189.             }
  190.         } else {
  191.             NodeType *w = x->parent->left;
  192.             if (w->color == RED) {
  193.                 w->color = BLACK;
  194.                 x->parent->color = RED;
  195.                 rotateRight (x->parent);
  196.                 w = x->parent->left;
  197.             }
  198.             if (w->right->color == BLACK && w->left->color == BLACK) {
  199.                 w->color = RED;
  200.                 x = x->parent;
  201.             } else {
  202.                 if (w->left->color == BLACK) {
  203.                     w->right->color = BLACK;
  204.                     w->color = RED;
  205.                     rotateLeft (w);
  206.                     w = x->parent->left;
  207.                 }
  208.                 w->color = x->parent->color;
  209.                 x->parent->color = BLACK;
  210.                 w->left->color = BLACK;
  211.                 rotateRight (x->parent);
  212.                 x = root;
  213.             }
  214.         }
  215.     }
  216.     x->color = BLACK;
  217. }
  218. // delete node
  219. RbtStatus rbtErase(NodeType * z) {
  220.     NodeType *x, *y;
  221.     if (z->left == SENTINEL || z->right == SENTINEL) {
  222.         // y has a SENTINEL node as a child
  223.         y = z;
  224.     } else {
  225.         // find tree successor with a SENTINEL node as a child
  226.         y = z->right;
  227.         while (y->left != SENTINEL) y = y->left;
  228.     }
  229.     // x is y's only child
  230.     if (y->left != SENTINEL)
  231.         x = y->left;
  232.     else
  233.         x = y->right;
  234.     // remove y from the parent chain
  235.     x->parent = y->parent;
  236.     if (y->parent)
  237.         if (y == y->parent->left)
  238.             y->parent->left = x;
  239.         else
  240.             y->parent->right = x;
  241.     else
  242.         root = x;
  243.     if (y != z) {
  244.         z->key = y->key;
  245.         z->val = y->val;
  246.     }
  247.     if (y->color == BLACK)
  248.         deleteFixup (x);
  249.     free (y);
  250.     return RBT_STATUS_OK;
  251. }
  252. // find key
  253. NodeType *rbtFind(KeyType key) {
  254.     NodeType *current;
  255.     current = root;
  256.     while(current != SENTINEL) {
  257.         if(compEQ(key, current->key)) {
  258.             return current;
  259.         } else {
  260.             current = compLT (key, current->key) ?
  261.                 current->left : current->right;
  262.         }
  263.     }
  264.     return NULL;
  265. }
  266. // in-order walk of tree
  267. void rbtInorder(NodeType *p, void (callback)(NodeType *)) {
  268.     if (p == SENTINEL) return;
  269.     rbtInorder(p->left, callback);
  270.     callback(p);
  271.     rbtInorder(p->right, callback);
  272. }
  273. // delete nodes depth-first
  274. void rbtDelete(NodeType *p) {
  275.     if (p == SENTINEL) return;
  276.     rbtDelete(p->left);
  277.     rbtDelete(p->right);
  278.     free(p);
  279. }
  280. void displayNode(NodeType *p) {
  281.     printf("%d %d/n", p->key, p->val.stuff);
  282. }
  283. int main(int argc, char **argv) {
  284.     int maxnum, ct;
  285.     KeyType key;
  286.     RbtStatus status;
  287.     // command-line:
  288.     //
  289.     //   rbt 2000
  290.     //      process 2000 records
  291.     NodeType *p;
  292.     maxnum = atoi(argv[1]);
  293.     printf("maxnum = %d/n", maxnum);
  294.     for (ct = 1000; ct; ct--) {
  295.         key = rand() % 1000 + 1;
  296.         if ((p = rbtFind(key)) != NULL) {
  297.    /*
  298.                      if (p->val.stuff != 10*key) printf("fail val/n");
  299.                         status = rbtErase(p);
  300.                         if (status) printf("fail: status = %d/n", status);*/
  301.             
  302.         } else {
  303.             ValType val;
  304.             val.stuff = 10*key;
  305.             status = rbtInsert(key, val);
  306.             if (status) printf("fail: status = %d/n", status);
  307.         }
  308.     }
  309.     for (ct = 1000; ct; ct--) {
  310.         key = rand() % 100 + 1;
  311.         if ((p = rbtFind(key)) != NULL) {
  312.              status = rbtErase(p);
  313.         }
  314.     }
  315.     // output nodes in order
  316.     rbtInorder(root, displayNode);
  317.     rbtDelete(root);
  318.     return 0;
  319. }
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值