rbtree.h

  1. #ifndef _RED_BLACK_TREE_H_
  2. #define _RED_BLACK_TREE_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. // 销毁红黑树
  27. void destroy_rbtree(RBRoot *root);
  28.  
  29. // 将结点插入到红黑树中。插入成功,返回0;失败返回-1。
  30. int insert_rbtree(RBRoot *root, Type key);
  31.  
  32. // 删除结点(key为节点的值)
  33. void delete_rbtree(RBRoot *root, Type key);
  34.  
  35. // 前序遍历"红黑树"
  36. void preorder_rbtree(RBRoot *root);
  37. // 中序遍历"红黑树"
  38. void inorder_rbtree(RBRoot *root);
  39. // 后序遍历"红黑树"
  40. void postorder_rbtree(RBRoot *root);
  41.  
  42. // (递归实现)查找"红黑树"中键值为key的节点。找到的话,返回0;否则,返回-1。
  43. int rbtree_search(RBRoot *root, Type key);
  44. // (非递归实现)查找"红黑树"中键值为key的节点。找到的话,返回0;否则,返回-1。
  45. int iterative_rbtree_search(RBRoot *root, Type key);
  46.  
  47. // 返回最小结点的值(将值保存到val中)。找到的话,返回0;否则返回-1。
  48. int rbtree_minimum(RBRoot *root, int *val);
  49. // 返回最大结点的值(将值保存到val中)。找到的话,返回0;否则返回-1。
  50. int rbtree_maximum(RBRoot *root, int *val);
  51.  
  52. // 打印红黑树
  53. void print_rbtree(RBRoot *root);
  54.  
  55. #endif

  

main.c

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

  

红黑树的C语言实现的更多相关文章

  1. 算法导论 之 红黑树 - 删除[C语言]【转】

    转自:https://blog.csdn.net/qifengzou/article/details/17608863 作者:邹祁峰 邮箱:Qifeng.zou.job@hotmail.com 博客: ...

  2. 红黑树(四)之 C++的实现

    概要 前面分别介绍红黑树的理论知识和红黑树的C语言实现.本章是红黑树的C++实现,若读者对红黑树的理论知识不熟悉,建立先学习红黑树的理论知识,再来学习本章. 目录1. 红黑树的介绍2. 红黑树的C++ ...

  3. 红黑树(二)之 C语言的实现

    概要 红黑树在日常的使用中比较常用,例如Java的TreeMap和TreeSet,C++的STL,以及Linux内核中都有用到.之前写过一篇文章专门介绍红黑树的理论知识,本文将给出红黑数的C语言的实现 ...

  4. 红黑树的删除详解与思路分析——不同于教科书上的算法(dart语言实现)

    对于红黑树的删除,看了数据结构的书,也看了很多网上的讲解和实现,但都不满意.很多讲解都是囫囵吞枣,知其然,不知其所以然,讲的晦涩难懂. 红黑树是平衡二叉树的一种,其删除算法是比较复杂的,因为删除后还要 ...

  5. 【数据结构】红黑树 C语言代码

    连看带写花了三天,中途被指针引用搞得晕晕乎乎的. 插入和删除的调整过程没有看原理,只看了方法,直接照着写的. 看了两份资料,一份是算法导论第12-13章, 另一份是网上的资料http://blog.c ...

  6. 算法导论学习---红黑树具体解释之插入(C语言实现)

    前面我们学习二叉搜索树的时候发如今一些情况下其高度不是非常均匀,甚至有时候会退化成一条长链,所以我们引用一些"平衡"的二叉搜索树.红黑树就是一种"平衡"的二叉搜 ...

  7. 红黑树插入与删除完整代码(dart语言实现)

    之前分析了红黑树的删除,这里附上红黑树的完整版代码,包括查找.插入.删除等.删除后修复实现了两种算法,均比之前的更为简洁.一种是我自己的实现,代码非常简洁,行数更少:一种是Linux.Java等源码版 ...

  8. 从2-3-4树到红黑树(下) Java与C的实现

    欢迎探讨,如有错误敬请指正 如需转载,请注明出处   http://www.cnblogs.com/nullzx/ 相关博客: 从2-3-4树到红黑树(上) 从2-3-4树到红黑树(中) 1. 实现技 ...

  9. 红黑树(三)之 Linux内核中红黑树的经典实现

    概要 前面分别介绍了红黑树的理论知识 以及 通过C语言实现了红黑树.本章继续会红黑树进行介绍,下面将Linux 内核中的红黑树单独移植出来进行测试验证.若读者对红黑树的理论知识不熟悉,建立先学习红黑树 ...

随机推荐

  1. 从英语单词shell想到的

    shell当初听到以为很高级 后来才知道只是壳而已 百度百科中解释为 shell 在计算机科学中,Shell俗称壳(用来区别于核),是指“提供使用者使用界面”的软件(命令解析器).它类似于DOS下的c ...

  2. 2018年EMUI系统能力分论坛来啦

    为鼓励开发者创新,挖掘前沿创新能力的应用及服务,帮开发者打造爆款应用的同时丰富终端消费者的用户体验,由设立10亿激励基金耀星计划扶持的华为创新竞赛平台即将开启. 竞赛平台将滚动推出AI.HAG.AR. ...

  3. linux jdk 安装另一种方法

    linux 7.2 安装 jdk方法: (1). 以root用户登录linux系统, 应用Xmanager把文件拷贝到linux 系统的根目录. (2). 进入opt/software建立jvm文件夹 ...

  4. BZOJ 1597: [Usaco2008 Mar]土地购买 斜率优化

    1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec  Memory Limit: 162 MB Description 农夫John准备扩大他的农场,他正在考虑N ...

  5. 基于EasyNVR二次开发实现业务需求:用户、权限、设备管理

    许多接触到EasyNVR的用户.开发者都会提出关于EasyNVR设备分组和账户设备关系映射的问题,我们参考目前大部分的视频能力输出平台的做法,EasyNVR目前只做了唯一的用户/密码(类比appkey ...

  6. mongo数据库中一条记录中某个属性是数组情形时 数据结构的定义

    package entity; import java.util.Date; import com.mongodb.BasicDBList;import com.mongodb.DBObject; p ...

  7. Hive 实际上对于所存储的文件的完整性以及数据内容是否和表结构一致无支配力

    数据位于hdfs路径下 load data into Table t1 load 执行的是复制文件的操作 create Table partitioned by () 创建了分区目录

  8. 【题解】P4247 [清华集训]序列操作(线段树修改DP)

    [题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...

  9. CUDA: 常量内存与事件

    常量内存: 常量内存用于保存在核函数执行期间不会发生变化的数据,在变量面前添加  __constant__  修饰符: __constant__  Sphere  s[SPHERES]; cudaMe ...

  10. Java for LeetCode 114 Flatten Binary Tree to Linked List

    Given a binary tree, flatten it to a linked list in-place. For example, Given 1 / \ 2 5 / \ \ 3 4 6 ...