鱼C论坛

 找回密码
 立即注册
查看: 3590|回复: 6

[技术交流] 【纯C实现】【非递归】AVL树删除, 插入等操作

[复制链接]
发表于 2015-2-15 13:21:55 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
纯C实现了AVL树, 非递归算法
实现了简单的范型, 这个AVL树是当作字典(即保持(key, value)对)用的(类似C++标准库的std::map), 也就是用AVL树实现了映射
测试插入4000000个数据(别数有几个0了, 是四百万), 生成的(key, value)对是随机的(但是可以保证4000000个数据中每一对数据的key都是唯一的), 插入4000000个数据后树的高度(在我测试过的情况中)为25左右
然后删除2000000个数据, 查找2000000个数据
所花时间大概在9秒到10秒之间(我看的手表计时......没有用time.h中的函数计时, 不是很准, 大家可以自己测试)
下面贴完整代码吧, 注释应该是够了, 可能没有太注意排版, 100多行代码全部塞一个函数里......凑合着看......
实现整个AVL树用了446行代码, 删除算法很多书都没有(我看的这本书有, 不过整个AVL树书上只是讲了思路, 没有代码), 连小甲鱼的视频里都没有哦, 而且非递归, 应该挺难得的吧......
贴代码:
注意stdbool.h VS貌似没有(微软貌似从来没有对C/C++标准很重视......stdbool.h是C99的内容), bool类型要自己定义
  1. #ifndef AVL_TREE_H
  2. #define AVL_TREE_H

  3. #include <stddef.h>
  4. #include <stdbool.h>

  5. struct AVLTreeHandle;
  6. typedef struct AVLTreeHandle * AVLTree;

  7. AVLTree CreateAVLTree(int (*cmp_key)(const void *, const void *),  
  8.                       size_t key_width, size_t value_width);
  9. bool InsertAVLTree(AVLTree avl, const void *key, const void *value);
  10. bool DeleteAVLTree(AVLTree avl, const void *key, void *value);
  11. void * SearchAVLTree(AVLTree avl, const void *key);
  12. bool IsAVLTreeEmpty(AVLTree avl);
  13. void ClearAVLTree(AVLTree avl);
  14. void DestroyAVLTree(AVLTree avl);

  15. #endif
复制代码

stdint.h貌似在VC10(也就是VS2010)和之前版本都没有, int8_t需要自己定义
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdint.h>
  4. #include <assert.h>
  5. #include "avl_tree.h"

  6. #define NONE  -1
  7. #define LEFT  0
  8. #define RIGHT 1
  9. #define LL    2
  10. #define LR    3
  11. #define RL    4
  12. #define RR    5

  13. typedef struct AVLTreeNode {
  14.         int8_t bf;
  15.         void *key;
  16.         void *value;
  17.         struct AVLTreeNode *parent;
  18.         struct AVLTreeNode *left_child;
  19.         struct AVLTreeNode *right_child;
  20. } AVLTreeNode;

  21. struct AVLTreeHandle {
  22.         int (*cmp_key)(const void *, const void *);
  23.         size_t key_width,
  24.                value_width;
  25.         AVLTreeNode *root;
  26. };

  27. static void LLRotate(AVLTreeNode *x);
  28. static void LRRotate(AVLTreeNode *x);
  29. static void RLRotate(AVLTreeNode *x);
  30. static void RRRotate(AVLTreeNode *x);
  31. static void DestroyTree(AVLTreeNode *root);
  32. static AVLTreeNode * FindPrev(AVLTreeNode *root);

  33. AVLTree CreateAVLTree(int (*cmp_key)(const void *, const void *),
  34.                       size_t key_width, size_t value_width)
  35. {
  36.         struct AVLTreeHandle *new = malloc(sizeof (struct AVLTreeHandle));
  37.         assert(new);

  38.         new->cmp_key = cmp_key;
  39.         new->key_width = key_width;
  40.         new->value_width = value_width;
  41.         new->root = NULL;
  42.         return new;
  43. }

  44. bool InsertAVLTree(AVLTree avl, const void *key, const void *value)
  45. {
  46.         AVLTreeNode *p = avl->root;
  47.         AVLTreeNode *pp = NULL;
  48.         AVLTreeNode *x = NULL;
  49.         int non_balanced_type, cmp_result;
  50.         /*********************************************
  51.          * x是在插入的路径上, 在插入前最后一个bf值为 *
  52.          * 1或-1的节点                               *
  53.          *********************************************/

  54.         while (p != NULL && (cmp_result = avl->cmp_key(key, p->key)) != 0) {
  55.                 pp = p;

  56.                 if (pp->bf == 1 || pp->bf == -1) {
  57.                         x = pp;
  58.                         non_balanced_type = NONE;
  59.                 }

  60.                 if (cmp_result < 0) {
  61.                         p = p->left_child;
  62.                         if (x != NULL) {
  63.                                 /* 根据插入路径确定不平衡类型 */
  64.                                 switch (non_balanced_type) {
  65.                                         case NONE:  non_balanced_type = LEFT; break;
  66.                                         case LEFT:  non_balanced_type = LL;   break;
  67.                                         case RIGHT: non_balanced_type = RL;   break;
  68.                                 }
  69.                         }
  70.                 }
  71.                 else {
  72.                         p = p->right_child;
  73.                         if (x != NULL) {
  74.                                 /* 根据插入路径确定不平衡类型 */
  75.                                 switch (non_balanced_type) {
  76.                                         case NONE:  non_balanced_type = RIGHT; break;
  77.                                         case LEFT:  non_balanced_type = LR;    break;
  78.                                         case RIGHT: non_balanced_type = RR;    break;
  79.                                 }
  80.                         }
  81.                 }
  82.         }

  83.         /* 键在原AVL树中不存在 */
  84.         if (p == NULL) {
  85.                 AVLTreeNode *new = malloc(sizeof (AVLTreeNode));
  86.                 bool insert_left, insert_right, is_balanced;
  87.                 int b;
  88.                 assert(new);

  89.                 new->key = malloc(avl->key_width);
  90.                 assert(new->key);
  91.                 new->value = malloc(avl->value_width);
  92.                 assert(new->value);
  93.                 new->parent = pp;
  94.                 new->left_child = NULL;
  95.                 new->right_child = NULL;

  96.                 memcpy(new->key, key, avl->key_width);
  97.                 memcpy(new->value, value, avl->value_width);
  98.                 new->bf = 0;

  99.                 /* 原树为空 */
  100.                 if (pp == NULL) {
  101.                         avl->root = new;
  102.                         return true;
  103.                 }

  104.                 insert_left = non_balanced_type == LL || non_balanced_type == LR || non_balanced_type == LEFT;
  105.                 insert_right = non_balanced_type == RR || non_balanced_type == RL || non_balanced_type == RIGHT;
  106.                 is_balanced = (x != NULL) && ((x->bf == 1 && insert_right) || (x->bf == -1 && insert_left));

  107.                 if (cmp_result < 0) {
  108.                         pp->left_child = new;
  109.                         ++pp->bf;
  110.                 }
  111.                 else {
  112.                         pp->right_child = new;
  113.                         --pp->bf;
  114.                 }
  115.                        

  116.                 /*************************************************************************************
  117.                  * 当插入路径上的节点在插入前平衡因子都为0的话, 修改从根节点到pp的父节点的平衡因子,  *
  118.                  * 否则修改从x到pp父节点的平衡因子(pp的平衡因子已经修改过)                           *
  119.                  *************************************************************************************/
  120.                 p = (x == NULL) ? avl->root : x;

  121.                 while (p != pp) {
  122.                         if (avl->cmp_key(key, p->key) < 0) {
  123.                                 ++p->bf;
  124.                                 p = p->left_child;
  125.                         }
  126.                         else {
  127.                                 --p->bf;
  128.                                 p = p->right_child;
  129.                         }
  130.                 }

  131.                 /* 树在插入后仍然保持平衡 */
  132.                 if (x == NULL || is_balanced)
  133.                         return true;

  134.                 /* 插入后树不平衡 */
  135.                 /* 根据不平衡类型执行对应旋转 */
  136.                 switch (non_balanced_type) {
  137.                         case LL: LLRotate(x);
  138.                                  x->right_child->bf = 0;
  139.                                  break;
  140.                         case LR: b = x->left_child->right_child->bf;
  141.                                  LRRotate(x);
  142.                                  x->left_child->bf = (b == -1) ? 1 : 0;
  143.                                  x->right_child->bf = (b == 1) ? -1 : 0;
  144.                                  break;
  145.                         case RL: b = x->right_child->left_child->bf;
  146.                                  RLRotate(x);
  147.                                  x->left_child->bf = (b == -1) ? 1 : 0;
  148.                                  x->right_child->bf = (b == 1) ? -1 : 0;
  149.                                  break;
  150.                         case RR: RRRotate(x);
  151.                                  x->left_child->bf = 0;
  152.                                  break;
  153.                         default: assert(0);     break;
  154.                 }
  155.                 x->bf = 0;
  156.                 return true;
  157.         }
  158.         return false;
  159. }


  160. bool DeleteAVLTree(AVLTree avl, const void *key, void *value)
  161. {
  162.         AVLTreeNode *p = avl->root, /* p指向要删除的节点 */
  163.                     *q = NULL, /* q指向p的父节点 */
  164.                     *c; /* c在下面会说明 */
  165.         int cmp_result;
  166.         bool lower = false;

  167.         while (p != NULL && (cmp_result = avl->cmp_key(key, p->key)) != 0) {
  168.                 q = p;
  169.                 p = (cmp_result < 0) ? p->left_child : p->right_child;
  170.         }

  171.         /* 没有找到关键字为key的节点 */
  172.         if (p == NULL)
  173.                 return false;

  174.         memcpy(value, p->value, avl->value_width);

  175.         /* 欲删除节点有两个孩子 */
  176.         if (p->left_child != NULL && p->right_child != NULL) {
  177.                 AVLTreeNode *prev = FindPrev(p);
  178.                 void *p_key = p->key, *p_value = p->value;

  179.                 p->key = prev->key;
  180.                 p->value = prev->value;
  181.                 prev->key = p_key;
  182.                 prev->value = p_value;

  183.                 p = prev;
  184.                 q = prev->parent;
  185.         }

  186.         /* c指向p唯一非空的子树(如果p为叶子节点c为NULL) */
  187.         c = (p->left_child != NULL) ? p->left_child : p->right_child;

  188.         if (p == avl->root) {
  189.                 avl->root = c;
  190.                 q = NULL;
  191.         } else if (p == q->left_child) {
  192.                 q->left_child = c;
  193.                 --q->bf;
  194.         } else {
  195.                 q->right_child = c;
  196.                 ++q->bf;
  197.         }

  198.         if (c != NULL)
  199.                 c->parent = q;

  200.         free(p->key);
  201.         free(p->value);
  202.         free(p);

  203.         while (q != NULL) {
  204.                 if (lower) {
  205.                         if (p == q->left_child)
  206.                                 --q->bf;
  207.                         else
  208.                                 ++q->bf;
  209.                 }

  210.                 if (q->bf == 0)
  211.                         lower = true;
  212.                 else if (q->bf == 1 || q->bf == -1)
  213.                         break;
  214.                 else {
  215.                         /* 树出现不平衡 */
  216.                         /* 除了R0型不平衡和L0型不平衡外, 其他不平衡矫正后都会使子树的高度减小 */
  217.                         int b;

  218.                         if (q->bf == 2) {
  219.                                 /* R型不平衡 */
  220.                                 int lbf = q->left_child->bf;

  221.                                 if (lbf == 0) {
  222.                                         /* R0型不平衡 */
  223.                                         LLRotate(q);
  224.                                         q->bf = -1;
  225.                                         q->right_child->bf = 1;
  226.                                         break;
  227.                                 } else if (lbf == 1) {
  228.                                         /* R1型不平衡 */
  229.                                         LLRotate(q);
  230.                                         q->bf = 0;
  231.                                         q->right_child->bf = 0;
  232.                                 } else {
  233.                                         /* R-1型不平衡 */
  234.                                         b = q->left_child->right_child->bf;
  235.                                         LRRotate(q);
  236.                                         q->bf = 0;
  237.                                         q->left_child->bf = (b == -1) ? 1 : 0;
  238.                                         q->right_child->bf = (b == 1) ? -1 : 0;
  239.                                 }
  240.                         } else {
  241.                                 /* L型不平衡 */
  242.                                 int rbf = q->right_child->bf;

  243.                                 if (rbf == 0) {
  244.                                         /* L0型不平衡 */
  245.                                         RRRotate(q);
  246.                                         q->bf = 1;
  247.                                         q->left_child->bf = -1;
  248.                                         break;
  249.                                 } else if (rbf == 1) {
  250.                                         /* L1型不平衡 */
  251.                                         b = q->right_child->left_child->bf;
  252.                                         RLRotate(q);
  253.                                         q->bf = 0;
  254.                                         q->left_child->bf = (b == -1) ? 1 : 0;
  255.                                         q->right_child->bf = (b == 1) ? -1 : 0;
  256.                                 } else {
  257.                                          /* L-1型不平衡 */
  258.                                         RRRotate(q);
  259.                                         q->bf = 0;
  260.                                         q->left_child->bf = 0;
  261.                                 }
  262.                         }
  263.                         lower = true;
  264.                 }

  265.                 /* 上升一层 */
  266.                 p = q;
  267.                 q = q->parent;
  268.         }

  269.         return true;
  270. }

  271. void * SearchAVLTree(AVLTree avl, const void *key)
  272. {
  273.         AVLTreeNode *p = avl->root;
  274.         int cmp_result;

  275.         while (p != NULL && (cmp_result = avl->cmp_key(key, p->key)) != 0)
  276.                 p = (cmp_result < 0) ? p->left_child : p->right_child;

  277.         return (p == NULL) ? NULL : p->value;
  278. }

  279. bool IsAVLTreeEmpty(AVLTree avl)
  280. {
  281.         return avl->root == NULL;
  282. }

  283. void ClearAVLTree(AVLTree avl)
  284. {
  285.         DestroyTree(avl->root);
  286.         avl->root = NULL;
  287. }

  288. void DestroyAVLTree(AVLTree avl)
  289. {
  290.         DestroyTree(avl->root);
  291.         free(avl);
  292. }

  293. static void LLRotate(AVLTreeNode *x)
  294. {
  295.         /*      X(2)                            Y(0)
  296.          *     /   \                           /    \
  297.          *   Y(1)   Xr     ---->             Yl     X(0)
  298.          *   / \     h                       h+1    /  \
  299.          * Yl   Yr                                 Yr  Xr
  300.          * h+1   h                                 h   h
  301.          */
  302.         AVLTreeNode *y = x->left_child, *xr = x->right_child;
  303.         void *x_key = x->key, *x_value = x->value;
  304.         /*      X(2)                            X(-2)
  305.          *     /   \                           /    \
  306.          *   Y(1)   Xr     ---->             Yl     Y(1)
  307.          *   / \     h                       h+1    /  \
  308.          * Yl   Yr                                 Yl  Yr
  309.          * h+1   h                                 h+1  h
  310.          */
  311.         x->left_child = y->left_child;
  312.         if (y->left_child != NULL)
  313.                 y->left_child->parent = x;
  314.         x->right_child = y;
  315.         /*      X(-2)                  Y(0)
  316.          *     /   \                  /    \
  317.          *   Yl     Y(1)    ---->    Yl    X(0)
  318.          *   h+1    /  \             h+1   /  \
  319.          *         Yl  Yr                 Yr  Xr
  320.          *         h+1  h                 h   h
  321.          */
  322.         x->key = y->key;
  323.         x->value = y->value;

  324.         y->key = x_key;
  325.         y->value = x_value;

  326.         y->left_child = y->right_child;
  327.         y->right_child = xr;
  328.         if (xr != NULL)
  329.                 xr->parent = y;
  330. }

  331. static void LRRotate(AVLTreeNode *x)
  332. {
  333.         RRRotate(x->left_child);
  334.         LLRotate(x);
  335. }

  336. static void RLRotate(AVLTreeNode *x)
  337. {
  338.         LLRotate(x->right_child);
  339.         RRRotate(x);
  340. }

  341. static void RRRotate(AVLTreeNode *x)
  342. {
  343.         /*     X(-2)                    Y(0)
  344.          *    /   \                    /   \
  345.          *   Xl   Y(-1)    ---->     X(0)   Yr
  346.          *   h    /   \              /  \   h+1
  347.          *       Yl    Yr           Xl   Yl
  348.          *       h     h+1          h    h
  349.          */
  350.         AVLTreeNode *y = x->right_child;
  351.         AVLTreeNode *xl = x->left_child;
  352.         void *x_key = x->key, *x_value = x->value;
  353.         /*     X(-2)                    Y(0)     
  354.          *    /   \                    /    \
  355.          *   Xl    Y(-1)   ---->     X(0)   Yr
  356.          *   h     /   \             /  \    h+1
  357.          *        Yl   Yr           Xl   Yl
  358.          *        h    h+1          h    h
  359.          */
  360.         x->right_child = y->right_child;
  361.         if (y->right_child != NULL)
  362.                 y->right_child->parent = x;
  363.         x->left_child = y;

  364.         y->right_child = y->left_child;
  365.         y->left_child = xl;
  366.         if (xl != NULL)
  367.                 xl->parent = y;

  368.         x->key = y->key;
  369.         x->value = y->value;

  370.         y->key = x_key;
  371.         y->value = x_value;
  372. }

  373. static void DestroyTree(AVLTreeNode *root)
  374. {
  375.         if (root != NULL) {
  376.                 DestroyTree(root->left_child);
  377.                 DestroyTree(root->right_child);
  378.                 free(root->key);
  379.                 free(root->value);
  380.                 free(root);
  381.         }
  382. }

  383. static AVLTreeNode * FindPrev(AVLTreeNode *root)
  384. {
  385.         for (root = root->left_child; root->right_child != NULL;
  386.              root = root->right_child)
  387.                 ;
  388.         return root;       
  389. }
复制代码

也许我的代码不是很好, 也恳请大神指教~
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-2-15 13:23:35 | 显示全部楼层
我发帖之前对代码做了小小的修改, 所以大家看到的代码少了一行, 变成了445行
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-2-15 13:25:12 | 显示全部楼层
另外这个源文件也只能用C语言编译器编译(不能用C++编译器), 因为里面有变量被命名为new, 而new是C++的关键字......用C++编译器编译的代码要做些修改
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-2-15 13:30:43 | 显示全部楼层
我也希望小甲鱼能把AVL树的删除课程补上......
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-2-15 13:33:29 | 显示全部楼层
支持学习了。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-2-15 16:19:05 | 显示全部楼层
范型->泛型......
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-2-19 20:46:54 | 显示全部楼层
进来看的朋友给个回复吧, 否则我会以为根本没人看我的帖的:cry
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-16 01:35

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表