免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 23176 | 回复: 34
打印 上一主题 下一主题

[算法] 红黑树的实现源码(C语言版) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-11-10 17:40 |只看该作者 |倒序浏览
不多说啥了,这里不讲理论, 需要的可以自己去看书(如算法导论等), 就给出一份实现代码, 供有需要的人参考之用, 前后写了好久, 参考的是linux内核中红黑树的实现代码:http://lxr.linux.no/linux/lib/rbtree.c

实现的操作有:插入, 查找, 删除.


  1. /*-----------------------------------------------------------
  2.     RB-Tree的插入和删除操作的实现算法
  3.     参考资料:
  4.     1) <<Introduction to algorithm>>
  5.     2) [url]http://lxr.linux.no/linux/lib/rbtree.c[/url]

  6.     作者:[url]http://www.cppblog.com/converse/[/url]
  7.     您可以自由的传播,修改这份代码,转载处请注明原作者

  8.     红黑树的几个性质:
  9.     1) 每个结点只有红和黑两种颜色
  10.     2) 根结点是黑色的
  11.     3)空节点是黑色的(红黑树中,根节点的parent以及所有叶节点lchild、rchild都不指向NULL,而是指向一个定义好的空节点)。
  12.     4) 如果一个结点是红色的,那么它的左右两个子结点的颜色是黑色的
  13.     5) 对于每个结点而言,从这个结点到叶子结点的任何路径上的黑色结点
  14.     的数目相同
  15. -------------------------------------------------------------*/

  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>

  19. typedef int key_t;
  20. typedef int data_t;

  21. typedef enum color_t
  22. {
  23.     RED = 0,
  24.     BLACK = 1
  25. }color_t;

  26. typedef struct rb_node_t
  27. {
  28.     struct rb_node_t *left, *right, *parent;
  29.     key_t key;
  30.     data_t data;
  31.     color_t color;
  32. }rb_node_t;

  33. /* forward declaration */
  34. rb_node_t* rb_insert(key_t key, data_t data, rb_node_t* root);
  35. rb_node_t* rb_search(key_t key, rb_node_t* root);
  36. rb_node_t* rb_erase(key_t key, rb_node_t* root);

  37. int main()
  38. {
  39.     int i, count = 900000;
  40.     key_t key;
  41.     rb_node_t* root = NULL, *node = NULL;
  42.    
  43.     srand(time(NULL));
  44.     for (i = 1; i < count; ++i)
  45.     {
  46.         key = rand() % count;
  47.         if ((root = rb_insert(key, i, root)))
  48.         {
  49.             printf("[i = %d] insert key %d success!\n", i, key);
  50.         }
  51.         else
  52.         {
  53.             printf("[i = %d] insert key %d error!\n", i, key);
  54.             exit(-1);
  55.         }

  56.         if ((node = rb_search(key, root)))
  57.         {
  58.             printf("[i = %d] search key %d success!\n", i, key);
  59.         }
  60.         else
  61.         {
  62.             printf("[i = %d] search key %d error!\n", i, key);
  63.             exit(-1);
  64.         }
  65.         if (!(i % 10))
  66.         {
  67.             if ((root = rb_erase(key, root)))
  68.             {
  69.                 printf("[i = %d] erase key %d success\n", i, key);
  70.             }
  71.             else
  72.             {
  73.                 printf("[i = %d] erase key %d error\n", i, key);
  74.             }
  75.         }
  76.     }

  77.     return 0;
  78. }

  79. static rb_node_t* rb_new_node(key_t key, data_t data)
  80. {
  81.     rb_node_t *node = (rb_node_t*)malloc(sizeof(struct rb_node_t));

  82.     if (!node)
  83.     {
  84.         printf("malloc error!\n");
  85.         exit(-1);
  86.     }
  87.     node->key = key, node->data = data;

  88.     return node;
  89. }

  90. /*-----------------------------------------------------------
  91. |   node           right
  92. |   / \    ==>     / \
  93. |   a  right     node  y
  94. |       / \           / \
  95. |       b  y         a   b
  96. -----------------------------------------------------------*/
  97. static rb_node_t* rb_rotate_left(rb_node_t* node, rb_node_t* root)
  98. {
  99.     rb_node_t* right = node->right;

  100.     if ((node->right = right->left))
  101.     {
  102.         right->left->parent = node;
  103.     }
  104.     right->left = node;

  105.     if ((right->parent = node->parent))
  106.     {
  107.         if (node == node->parent->right)
  108.         {
  109.             node->parent->right = right;
  110.         }
  111.         else
  112.         {
  113.             node->parent->left = right;
  114.         }
  115.     }
  116.     else
  117.     {
  118.         root = right;
  119.     }
  120.     node->parent = right;

  121.     return root;
  122. }

  123. /*-----------------------------------------------------------
  124. |       node           left
  125. |       / \            / \
  126. |    left  y   ==>    a   node
  127. |   / \               / \
  128. |  a   b             b   y
  129. -----------------------------------------------------------*/
  130. static rb_node_t* rb_rotate_right(rb_node_t* node, rb_node_t* root)
  131. {
  132.     rb_node_t* left = node->left;

  133.     if ((node->left = left->right))
  134.     {
  135.         left->right->parent = node;
  136.     }
  137.     left->right = node;

  138.     if ((left->parent = node->parent))
  139.     {
  140.         if (node == node->parent->right)
  141.         {
  142.             node->parent->right = left;
  143.         }
  144.         else
  145.         {
  146.             node->parent->left = left;
  147.         }
  148.     }
  149.     else
  150.     {
  151.         root = left;
  152.     }
  153.     node->parent = left;

  154.     return root;
  155. }

  156. static rb_node_t* rb_insert_rebalance(rb_node_t *node, rb_node_t *root)
  157. {
  158.     rb_node_t *parent, *gparent, *uncle, *tmp;

  159.     while ((parent = node->parent) && parent->color == RED)
  160.     {
  161.         gparent = parent->parent;

  162.         if (parent == gparent->left)
  163.         {
  164.             uncle = gparent->right;
  165.             if (uncle && uncle->color == RED)
  166.             {
  167.                 uncle->color = BLACK;
  168.                 parent->color = BLACK;
  169.                 gparent->color = RED;
  170.                 node = gparent;
  171.             }
  172.             else
  173.             {
  174.                 if (parent->right == node)
  175.                 {
  176.                     root = rb_rotate_left(parent, root);
  177.                     tmp = parent;
  178.                     parent = node;
  179.                     node = tmp;
  180.                 }

  181.                 parent->color = BLACK;
  182.                 gparent->color = RED;
  183.                 root = rb_rotate_right(gparent, root);
  184.             }
  185.         }
  186.         else
  187.         {
  188.             uncle = gparent->left;
  189.             if (uncle && uncle->color == RED)
  190.             {
  191.                 uncle->color = BLACK;
  192.                 parent->color = BLACK;
  193.                 gparent->color = RED;
  194.                 node = gparent;
  195.             }
  196.             else
  197.             {
  198.                 if (parent->left == node)
  199.                 {
  200.                     root = rb_rotate_right(parent, root);
  201.                     tmp = parent;
  202.                     parent = node;
  203.                     node = tmp;
  204.                 }

  205.                 parent->color = BLACK;
  206.                 gparent->color = RED;
  207.                 root = rb_rotate_left(gparent, root);
  208.             }
  209.         }
  210.     }

  211.     root->color = BLACK;

  212.     return root;
  213. }

  214. static rb_node_t* rb_erase_rebalance(rb_node_t *node, rb_node_t *parent, rb_node_t *root)
  215. {
  216.     rb_node_t *other, *o_left, *o_right;

  217.     while ((!node || node->color == BLACK) && node != root)
  218.     {
  219.         if (parent->left == node)
  220.         {
  221.             other = parent->right;
  222.             if (other->color == RED)
  223.             {
  224.                 other->color = BLACK;
  225.                 parent->color = RED;
  226.                 root = rb_rotate_left(parent, root);
  227.                 other = parent->right;
  228.             }
  229.             if ((!other->left || other->left->color == BLACK) &&
  230.                 (!other->right || other->right->color == BLACK))
  231.             {
  232.                 other->color = RED;
  233.                 node = parent;
  234.                 parent = node->parent;
  235.             }
  236.             else
  237.             {
  238.                 if (!other->right || other->right->color == BLACK)
  239.                 {
  240.                     if ((o_left = other->left))
  241.                     {
  242.                         o_left->color = BLACK;
  243.                     }
  244.                     other->color = RED;
  245.                     root = rb_rotate_right(other, root);
  246.                     other = parent->right;
  247.                 }
  248.                 other->color = parent->color;
  249.                 parent->color = BLACK;
  250.                 if (other->right)
  251.                 {
  252.                     other->right->color = BLACK;
  253.                 }
  254.                 root = rb_rotate_left(parent, root);
  255.                 node = root;
  256.                 break;
  257.             }
  258.         }
  259.         else
  260.         {
  261.             other = parent->left;
  262.             if (other->color == RED)
  263.             {
  264.                 other->color = BLACK;
  265.                 parent->color = RED;
  266.                 root = rb_rotate_right(parent, root);
  267.                 other = parent->left;
  268.             }
  269.             if ((!other->left || other->left->color == BLACK) &&
  270.                 (!other->right || other->right->color == BLACK))
  271.             {
  272.                 other->color = RED;
  273.                 node = parent;
  274.                 parent = node->parent;
  275.             }
  276.             else
  277.             {
  278.                 if (!other->left || other->left->color == BLACK)
  279.                 {
  280.                     if ((o_right = other->right))
  281.                     {
  282.                         o_right->color = BLACK;
  283.                     }
  284.                     other->color = RED;
  285.                     root = rb_rotate_left(other, root);
  286.                     other = parent->left;
  287.                 }
  288.                 other->color = parent->color;
  289.                 parent->color = BLACK;
  290.                 if (other->left)
  291.                 {
  292.                     other->left->color = BLACK;
  293.                 }
  294.                 root = rb_rotate_right(parent, root);
  295.                 node = root;
  296.                 break;
  297.             }
  298.         }
  299.     }

  300.     if (node)
  301.     {
  302.         node->color = BLACK;
  303.     }

  304.     return root;
  305. }

  306. static rb_node_t* rb_search_auxiliary(key_t key, rb_node_t* root, rb_node_t** save)
  307. {
  308.     rb_node_t *node = root, *parent = NULL;
  309.     int ret;

  310.     while (node)
  311.     {
  312.         parent = node;
  313.         ret = node->key - key;
  314.         if (0 < ret)
  315.         {
  316.             node = node->left;
  317.         }
  318.         else if (0 > ret)
  319.         {
  320.             node = node->right;
  321.         }
  322.         else
  323.         {
  324.             return node;
  325.         }
  326.     }

  327.     if (save)
  328.     {
  329.         *save = parent;
  330.     }

  331.     return NULL;
  332. }

  333. rb_node_t* rb_insert(key_t key, data_t data, rb_node_t* root)
  334. {
  335.     rb_node_t *parent = NULL, *node;

  336.     parent = NULL;
  337.     if ((node = rb_search_auxiliary(key, root, &parent)))
  338.     {
  339.         return root;
  340.     }

  341.     node = rb_new_node(key, data);
  342.     node->parent = parent;
  343.     node->left = node->right = NULL;
  344.     node->color = RED;

  345.     if (parent)
  346.     {
  347.         if (parent->key > key)
  348.         {
  349.             parent->left = node;
  350.         }
  351.         else
  352.         {
  353.             parent->right = node;
  354.         }
  355.     }
  356.     else
  357.     {
  358.         root = node;
  359.     }

  360.     return rb_insert_rebalance(node, root);
  361. }

  362. rb_node_t* rb_search(key_t key, rb_node_t* root)
  363. {
  364.     return rb_search_auxiliary(key, root, NULL);
  365. }

  366. rb_node_t* rb_erase(key_t key, rb_node_t *root)
  367. {
  368.     rb_node_t *child, *parent, *old, *left, *node;
  369.     color_t color;

  370.     if (!(node = rb_search_auxiliary(key, root, NULL)))
  371.     {
  372.         printf("key %d is not exist!\n");
  373.         return root;
  374.     }

  375.     old = node;

  376.     if (node->left && node->right)
  377.     {
  378.         node = node->right;
  379.         while ((left = node->left) != NULL)
  380.         {
  381.             node = left;
  382.         }
  383.         child = node->right;
  384.         parent = node->parent;
  385.         color = node->color;

  386.         if (child)
  387.         {
  388.             child->parent = parent;
  389.         }
  390.         if (parent)
  391.         {
  392.             if (parent->left == node)
  393.             {
  394.                 parent->left = child;
  395.             }
  396.             else
  397.             {
  398.                 parent->right = child;
  399.             }
  400.         }
  401.         else
  402.         {
  403.             root = child;
  404.         }

  405.         if (node->parent == old)
  406.         {
  407.             parent = node;
  408.         }

  409.         node->parent = old->parent;
  410.         node->color = old->color;
  411.         node->right = old->right;
  412.         node->left = old->left;

  413.         if (old->parent)
  414.         {
  415.             if (old->parent->left == old)
  416.             {
  417.                 old->parent->left = node;
  418.             }
  419.             else
  420.             {
  421.                 old->parent->right = node;
  422.             }
  423.         }
  424.         else
  425.         {
  426.             root = node;
  427.         }

  428.         old->left->parent = node;
  429.         if (old->right)
  430.         {
  431.             old->right->parent = node;
  432.         }
  433.     }
  434.     else
  435.     {
  436.         if (!node->left)
  437.         {
  438.             child = node->right;
  439.         }
  440.         else if (!node->right)
  441.         {
  442.             child = node->left;
  443.         }
  444.         parent = node->parent;
  445.         color = node->color;

  446.         if (child)
  447.         {
  448.             child->parent = parent;
  449.         }
  450.         if (parent)
  451.         {
  452.             if (parent->left == node)
  453.             {
  454.                 parent->left = child;
  455.             }
  456.             else
  457.             {
  458.                 parent->right = child;
  459.             }
  460.         }
  461.         else
  462.         {
  463.             root = child;
  464.         }
  465.     }

  466.     free(old);

  467.     if (color == BLACK)
  468.     {
  469.         root = rb_erase_rebalance(child, parent, root);
  470.     }

  471.     return root;
  472. }


复制代码

[ 本帖最后由 converse 于 2008-11-11 19:20 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2008-11-10 17:47 |只看该作者
版权协议?

论坛徽章:
0
3 [报告]
发表于 2008-11-10 22:03 |只看该作者
收藏

论坛徽章:
0
4 [报告]
发表于 2008-11-10 22:17 |只看该作者
暂时看不懂,先顶一个先

论坛徽章:
0
5 [报告]
发表于 2008-11-11 09:41 |只看该作者
红黑树在新的调度器(CFS)中被使用。这个东西很牛。

LZ能不能写得再细一点!!

论坛徽章:
0
6 [报告]
发表于 2008-11-11 09:50 |只看该作者
原帖由 nhuczp 于 2008-11-11 09:41 发表
红黑树在新的调度器(CFS)中被使用。这个东西很牛。

LZ能不能写得再细一点!!

你去看《算法导论》吧
内核中实现的红黑树是很中规中矩的,跟算法导论上讲的完全一样。

论坛徽章:
0
7 [报告]
发表于 2008-11-11 13:37 |只看该作者
有时间研究下,学习了。。。


LS的也在中关村吗?

[ 本帖最后由 veking 于 2008-11-11 13:40 编辑 ]

论坛徽章:
52
码神
日期:2017-03-28 10:27:10综合交流区版块每日发帖之星
日期:2015-10-11 06:20:00综合交流区版块每日发帖之星
日期:2015-09-28 06:20:00综合交流区版块每日发帖之星
日期:2015-09-22 06:20:00每日论坛发贴之星
日期:2015-09-12 06:20:00综合交流区版块每日发帖之星
日期:2015-09-12 06:20:00综合交流区版块每日发帖之星
日期:2015-09-08 06:20:00综合交流区版块每日发帖之星
日期:2015-09-05 06:20:00综合交流区版块每日发帖之星
日期:2015-09-04 06:20:002015亚冠之德黑兰石油
日期:2015-09-01 10:41:53每日论坛发贴之星
日期:2015-10-11 06:20:00综合交流区版块每日发帖之星
日期:2015-10-12 06:20:00
8 [报告]
发表于 2008-11-11 14:42 |只看该作者
原帖由 converse 于 2008-11-10 17:40 发表
不多说啥了,这里不讲理论, 需要的可以自己去看书(如算法导论等), 就给出一份实现代码, 供有需要的人参考之用, 前后写了好久, 参考的是linux内核中红黑树的实现代码:http://lxr.linux.no/linux/lib/rbtree.c

...


感谢,并且收藏了。

论坛徽章:
0
9 [报告]
发表于 2008-11-11 14:50 |只看该作者
先收藏,谢谢

论坛徽章:
0
10 [报告]
发表于 2008-11-17 11:03 |只看该作者
http://www.freebsd.org/cgi/cvswe ... ib/rb.h?rev=1.4.2.1;content-type=text%2Fplain


/******************************************************************************
*
* Copyright (C) 2008 Jason Evans <jasone@FreeBSD.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice(s), this list of conditions and the following disclaimer
*    unmodified other than the allowable addition of one or more
*    copyright notices.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice(s), this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*
* cpp macro implementation of left-leaning red-black trees.
*
* Usage:
*
*   (Optional, see assert(3).)
*   #define NDEBUG
*
*   (Required.)
*   #include <assert.h>
*   #include <rb.h>
*   ...
*
* All operations are done non-recursively.  Parent pointers are not used, and
* color bits are stored in the least significant bit of right-child pointers,
* thus making node linkage as compact as is possible for red-black trees.
*
* Some macros use a comparison function pointer, which is expected to have the
* following prototype:
*
*   int (a_cmp *)(a_type *a_node, a_type *a_other);
*                         ^^^^^^
*                      or a_key
*
* Interpretation of comparision function return values:
*
*   -1 : a_node <  a_other
*    0 : a_node == a_other
*    1 : a_node >  a_other
*
* In all cases, the a_node or a_key macro argument is the first argument to the
* comparison function, which makes it possible to write comparison functions
* that treat the first argument specially.
*
******************************************************************************/

#ifndef RB_H_
#define        RB_H_

#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/stdlib/rb.h,v 1.4.2.1 2008/06/16 23:42:05 jasone Exp $");

/* Node structure. */
#define        rb_node(a_type)                                                        \
struct {                                                                \
    a_type *rbn_left;                                                        \
    a_type *rbn_right_red;                                                \
}

/* Root structure. */
#define        rb_tree(a_type)                                                        \
struct {                                                                \
    a_type *rbt_root;                                                        \
    a_type rbt_nil;                                                        \
}

/* Left accessors. */
#define        rbp_left_get(a_type, a_field, a_node)                                \
    ((a_node)->a_field.rbn_left)
#define        rbp_left_set(a_type, a_field, a_node, a_left) do {                \
    (a_node)->a_field.rbn_left = a_left;                                \
} while (0)

/* Right accessors. */
#define        rbp_right_get(a_type, a_field, a_node)                                \
    ((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red)                \
      & ((ssize_t)-2)))
#define        rbp_right_set(a_type, a_field, a_node, a_right) do {                \
    (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right)        \
      | (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1)));        \
} while (0)

/* Color accessors. */
#define        rbp_red_get(a_type, a_field, a_node)                                \
    ((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red)                \
      & ((size_t)1)))
#define        rbp_color_set(a_type, a_field, a_node, a_red) do {                \
    (a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t)                \
      (a_node)->a_field.rbn_right_red) & ((ssize_t)-2))                        \
      | ((ssize_t)a_red));                                                \
} while (0)
#define        rbp_red_set(a_type, a_field, a_node) do {                        \
    (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t)                \
      (a_node)->a_field.rbn_right_red) | ((size_t)1));                        \
} while (0)
#define        rbp_black_set(a_type, a_field, a_node) do {                        \
    (a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t)                \
      (a_node)->a_field.rbn_right_red) & ((ssize_t)-2));                \
} while (0)

/* Node initializer. */
#define        rbp_node_new(a_type, a_field, a_tree, a_node) do {                \
    rbp_left_set(a_type, a_field, (a_node), &(a_tree)->rbt_nil);        \
    rbp_right_set(a_type, a_field, (a_node), &(a_tree)->rbt_nil);        \
    rbp_red_set(a_type, a_field, (a_node));                                \
} while (0)

/* Tree initializer. */
#define        rb_new(a_type, a_field, a_tree) do {                                \
    (a_tree)->rbt_root = &(a_tree)->rbt_nil;                                \
    rbp_node_new(a_type, a_field, a_tree, &(a_tree)->rbt_nil);                \
    rbp_black_set(a_type, a_field, &(a_tree)->rbt_nil);                        \
} while (0)

/* Tree operations. */
#define        rbp_black_height(a_type, a_field, a_tree, r_height) do {        \
    a_type *rbp_bh_t;                                                        \
    for (rbp_bh_t = (a_tree)->rbt_root, (r_height) = 0;                        \
      rbp_bh_t != &(a_tree)->rbt_nil;                                        \
      rbp_bh_t = rbp_left_get(a_type, a_field, rbp_bh_t)) {                \
        if (rbp_red_get(a_type, a_field, rbp_bh_t) == false) {                \
            (r_height)++;                                                \
        }                                                                \
    }                                                                        \
} while (0)

#define        rbp_first(a_type, a_field, a_tree, a_root, r_node) do {                \
    for ((r_node) = (a_root);                                                \
      rbp_left_get(a_type, a_field, (r_node)) != &(a_tree)->rbt_nil;        \
      (r_node) = rbp_left_get(a_type, a_field, (r_node))) {                \
    }                                                                        \
} while (0)

#define        rbp_last(a_type, a_field, a_tree, a_root, r_node) do {                \
    for ((r_node) = (a_root);                                                \
      rbp_right_get(a_type, a_field, (r_node)) != &(a_tree)->rbt_nil;        \
      (r_node) = rbp_right_get(a_type, a_field, (r_node))) {                \
    }                                                                        \
} while (0)

#define        rbp_next(a_type, a_field, a_cmp, a_tree, a_node, r_node) do {        \
    if (rbp_right_get(a_type, a_field, (a_node))                        \
      != &(a_tree)->rbt_nil) {                                                \
        rbp_first(a_type, a_field, a_tree, rbp_right_get(a_type,        \
          a_field, (a_node)), (r_node));                                \
    } else {                                                                \
        a_type *rbp_n_t = (a_tree)->rbt_root;                                \
        assert(rbp_n_t != &(a_tree)->rbt_nil);                                \
        (r_node) = &(a_tree)->rbt_nil;                                        \
        while (true) {                                                        \
            int rbp_n_cmp = (a_cmp)((a_node), rbp_n_t);                        \
            if (rbp_n_cmp < 0) {                                        \
                (r_node) = rbp_n_t;                                        \
                rbp_n_t = rbp_left_get(a_type, a_field, rbp_n_t);        \
            } else if (rbp_n_cmp > 0) {                                        \
                rbp_n_t = rbp_right_get(a_type, a_field, rbp_n_t);        \
            } else {                                                        \
                break;                                                        \
            }                                                                \
            assert(rbp_n_t != &(a_tree)->rbt_nil);                        \
        }                                                                \
    }                                                                        \
} while (0)

#define        rbp_prev(a_type, a_field, a_cmp, a_tree, a_node, r_node) do {        \
    if (rbp_left_get(a_type, a_field, (a_node)) != &(a_tree)->rbt_nil) {\
        rbp_last(a_type, a_field, a_tree, rbp_left_get(a_type,                \
          a_field, (a_node)), (r_node));                                \
    } else {                                                                \
        a_type *rbp_p_t = (a_tree)->rbt_root;                                \
        assert(rbp_p_t != &(a_tree)->rbt_nil);                                \
        (r_node) = &(a_tree)->rbt_nil;                                        \
        while (true) {                                                        \
            int rbp_p_cmp = (a_cmp)((a_node), rbp_p_t);                        \
            if (rbp_p_cmp < 0) {                                        \
                rbp_p_t = rbp_left_get(a_type, a_field, rbp_p_t);        \
            } else if (rbp_p_cmp > 0) {                                        \
                (r_node) = rbp_p_t;                                        \
                rbp_p_t = rbp_right_get(a_type, a_field, rbp_p_t);        \
            } else {                                                        \
                break;                                                        \
            }                                                                \
            assert(rbp_p_t != &(a_tree)->rbt_nil);                        \
        }                                                                \
    }                                                                        \
} while (0)

#define        rb_first(a_type, a_field, a_tree, r_node) do {                        \
    rbp_first(a_type, a_field, a_tree, (a_tree)->rbt_root, (r_node));        \
    if ((r_node) == &(a_tree)->rbt_nil) {                                \
        (r_node) = NULL;                                                \
    }                                                                        \
} while (0)

#define        rb_last(a_type, a_field, a_tree, r_node) do {                        \
    rbp_last(a_type, a_field, a_tree, (a_tree)->rbt_root, r_node);        \
    if ((r_node) == &(a_tree)->rbt_nil) {                                \
        (r_node) = NULL;                                                \
    }                                                                        \
} while (0)

#define        rb_next(a_type, a_field, a_cmp, a_tree, a_node, r_node) do {        \
    rbp_next(a_type, a_field, a_cmp, a_tree, (a_node), (r_node));        \
    if ((r_node) == &(a_tree)->rbt_nil) {                                \
        (r_node) = NULL;                                                \
    }                                                                        \
} while (0)

#define        rb_prev(a_type, a_field, a_cmp, a_tree, a_node, r_node) do {        \
    rbp_prev(a_type, a_field, a_cmp, a_tree, (a_node), (r_node));        \
    if ((r_node) == &(a_tree)->rbt_nil) {                                \
        (r_node) = NULL;                                                \
    }                                                                        \
} while (0)

#define        rb_search(a_type, a_field, a_cmp, a_tree, a_key, r_node) do {        \
    int rbp_se_cmp;                                                        \
    (r_node) = (a_tree)->rbt_root;                                        \
    while ((r_node) != &(a_tree)->rbt_nil                                \
      && (rbp_se_cmp = (a_cmp)((a_key), (r_node))) != 0) {                \
        if (rbp_se_cmp < 0) {                                                \
            (r_node) = rbp_left_get(a_type, a_field, (r_node));                \
        } else {                                                        \
            (r_node) = rbp_right_get(a_type, a_field, (r_node));        \
        }                                                                \
    }                                                                        \
    if ((r_node) == &(a_tree)->rbt_nil) {                                \
        (r_node) = NULL;                                                \
    }                                                                        \
} while (0)

/*
* Find a match if it exists.  Otherwise, find the next greater node, if one
* exists.
*/
#define        rb_nsearch(a_type, a_field, a_cmp, a_tree, a_key, r_node) do {        \
    a_type *rbp_ns_t = (a_tree)->rbt_root;                                \
    (r_node) = NULL;                                                        \
    while (rbp_ns_t != &(a_tree)->rbt_nil) {                                \
        int rbp_ns_cmp = (a_cmp)((a_key), rbp_ns_t);                        \
        if (rbp_ns_cmp < 0) {                                                \
            (r_node) = rbp_ns_t;                                        \
            rbp_ns_t = rbp_left_get(a_type, a_field, rbp_ns_t);                \
        } else if (rbp_ns_cmp > 0) {                                        \
            rbp_ns_t = rbp_right_get(a_type, a_field, rbp_ns_t);        \
        } else {                                                        \
            (r_node) = rbp_ns_t;                                        \
            break;                                                        \
        }                                                                \
    }                                                                        \
} while (0)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP