免费注册 查看新帖 |

Chinaunix

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

[C] 二叉平衡树AVL的插入和删除的C实现源码 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-11-03 21:28 |只看该作者 |倒序浏览
复习数据结构,顺便用C实现了一下二叉平衡树AVL的插入和删除算法
共享一下,呵呵


  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <errno.h>
  5. #include <assert.h>

  6. typedef struct node node;

  7. struct node
  8. {
  9.   node* parent;
  10.   node* left;
  11.   node* right;
  12.   int   balance;  //左右子树高度之差
  13.   int   key;
  14. };

  15. extern void traverseAVL1(node* root); //中序遍历, 下面定义

  16. extern void traverseAVL2(node* root); //前序遍历, 下面定义

  17. int searchNode(int key, node* root, node** parent) //按key查找结点
  18. {
  19.   node* temp;
  20.   assert(root != NULL);
  21.   temp = root;
  22.   *parent = root->parent;
  23.   while (temp !=NULL)
  24.   {
  25.     if (temp->key == key)
  26.       return 1;
  27.     else
  28.     {
  29.        *parent = temp;
  30.       if (temp->key > key)
  31.         temp = temp->left;
  32.       else
  33.         temp = temp->right;
  34.     }
  35.   }
  36.   return 0;

  37. }

  38. node* minNode(node* root) //树root的最小结点
  39. {
  40.   if (root == NULL)
  41.     return NULL;
  42.   while (root->left != NULL)
  43.     root = root->left;
  44.   return root;
  45. }

  46. node* maxNode(node* root) //树root的最大结点
  47. {
  48.   if (root == NULL)
  49.     return NULL;
  50.   while (root->right != NULL)
  51.     root = root->right;
  52.   return root;
  53. }

  54. node* preNode(node* target) //求前驱结点
  55. {
  56.   if (target == NULL)
  57.     return NULL;
  58.   if (target->left != NULL)
  59.     return maxNode(target->left);
  60.   else
  61.     while ((target->parent!=NULL) && (target!=target->parent->right))
  62.       target = target->parent;
  63.   return target->parent;
  64. }

  65. node* nextNode(node* target) //求后继结点
  66. {
  67.   if (target == NULL)
  68.     return NULL;
  69.   if (target->right != NULL)
  70.     return minNode(target->right);
  71.   else
  72.     while ((target->parent!=NULL) && (target!=target->parent->left))
  73.       target = target->parent;
  74.   return target->parent;
  75. }

  76. node* adjustAVL(node* root, node* parent, node* child)
  77. {
  78.   node *cur;
  79.   assert((parent != NULL)&&(child != NULL));
  80.   switch (parent->balance)
  81.   {
  82.   case 2:
  83.     if (child->balance == -1)//LR型
  84.     {
  85.       cur = child->right;
  86.       cur->parent = parent->parent;
  87.       child->right = cur->left;
  88.       if (cur->left != NULL)
  89.         cur->left->parent = child;
  90.       parent->left = cur->right;
  91.       if (cur->right != NULL)
  92.         cur->right->parent = parent;
  93.       cur->left = child;
  94.       child->parent = cur;
  95.       cur->right = parent;
  96.       if (parent->parent != NULL)
  97.         if (parent->parent->left == parent)
  98.           parent->parent->left = cur;
  99.         else parent->parent->right = cur;
  100.       else
  101.         root = cur;
  102.       parent->parent = cur;
  103.       if (cur->balance == 0)
  104.       {
  105.         parent->balance = 0;
  106.         child->balance = 0;
  107.       }
  108.       else if (cur->balance == -1)
  109.       {
  110.         parent->balance = 0;
  111.         child->balance = 1;
  112.       }
  113.       else
  114.       {
  115.         parent->balance = -1;
  116.         child->balance = 0;
  117.       }
  118.       cur->balance = 0;
  119.     }
  120.     else //LL型
  121.     {
  122.       child->parent = parent->parent;
  123.       parent->left = child->right;
  124.       if (child->right != NULL)
  125.         child->right->parent = parent;
  126.       child->right = parent;
  127.       if (parent->parent != NULL)
  128.         if (parent->parent->left == parent)
  129.           parent->parent->left = child;
  130.         else parent->parent->right = child;
  131.       else
  132.         root = child;
  133.       parent->parent = child;
  134.       if (child->balance == 1) //插入时
  135.       {
  136.         child->balance = 0;
  137.         parent->balance = 0;
  138.       }
  139.       else //删除时
  140.       {
  141.         child->balance = -1;
  142.         parent->balance = 1;
  143.       }
  144.     }
  145.    break;
  146.    
  147.   case -2:
  148.     if (child->balance == 1) //RL型
  149.     {
  150.       cur = child->left;
  151.       cur->parent = parent->parent;
  152.       child->left = cur->right;
  153.       if (cur->right != NULL)
  154.         cur->right->parent = child;
  155.       parent->right = cur->left;
  156.       if (cur->left != NULL)
  157.         cur->left->parent = parent;
  158.       cur->left = parent;
  159.       cur->right = child;
  160.       child->parent = cur;
  161.       if (parent->parent != NULL)
  162.         if (parent->parent->left == parent)
  163.           parent->parent->left = cur;
  164.         else parent->parent->right = cur;
  165.       else
  166.         root = cur;
  167.       parent->parent = cur;
  168.       if (cur->balance == 0)
  169.       {
  170.         parent->balance = 0;
  171.         child->balance = 0;
  172.       }
  173.       else if (cur->balance == 1)
  174.       {
  175.         parent->balance = 0;
  176.         child->balance = -1;
  177.       }
  178.       else
  179.       {
  180.         parent->balance = 1;
  181.         child->balance = 0;
  182.       }
  183.       cur->balance = 0;
  184.     }
  185.     else  //RR型
  186.     {
  187.       child->parent = parent->parent;
  188.       parent->right = child->left;
  189.       if (child->left != NULL)
  190.         child->left->parent = parent;
  191.       child->left = parent;
  192.       if (parent->parent != NULL)
  193.         if (parent->parent->left == parent)
  194.           parent->parent->left = child;
  195.         else parent->parent->right = child;
  196.       else
  197.         root = child;
  198.       parent->parent = child;
  199.       if (child->balance == -1) //插入时
  200.       {
  201.         child->balance = 0;
  202.         parent->balance = 0;
  203.       }
  204.       else //删除时
  205.       {
  206.         child->balance = 1;
  207.         parent->balance = -1;
  208.       }
  209.     }
  210.     break;
  211.   }
  212.   return root;
  213. }


  214. node* insertNode(int key, node* root)
  215. {
  216.   node *parent, *cur, *child;
  217.   assert (root != NULL);
  218.   if (searchNode(key, root, &parent)) //结点已存在
  219.     return root;
  220.   else
  221.   {
  222.     cur = (node*)malloc(sizeof(node));
  223.     cur->parent = parent;
  224.     cur->key = key;
  225.     cur->left = NULL;
  226.     cur->right = NULL;
  227.     cur->balance = 0;
  228.     if (key<parent->key)
  229.     {
  230.       parent->left = cur;
  231.       child = parent->left;
  232.     }
  233.     else
  234.     {
  235.       parent->right = cur;
  236.       child = parent->right;
  237.     }
  238.    
  239.     while ((parent != NULL)) //查找需要调整的最小子树
  240.     {
  241.       if (child == parent->left)
  242.         if (parent->balance == -1)
  243.         {
  244.           parent->balance = 0;
  245.           return root;
  246.         }
  247.         else if (parent->balance == 1)
  248.         {
  249.           parent->balance = 2;
  250.           break;
  251.         }
  252.         else
  253.         {
  254.           parent->balance = 1;
  255.           child = parent;
  256.           parent = parent->parent;
  257.         }
  258.       else if (parent->balance == 1)
  259.       {
  260.         parent->balance = 0;
  261.         return root;
  262.       }
  263.       else if (parent->balance == -1)
  264.       {
  265.         parent->balance = -2;
  266.         break;
  267.       }
  268.       else
  269.       {
  270.         parent->balance = -1;
  271.         child = parent;
  272.         parent = parent->parent;
  273.       }
  274.     }
  275.    
  276.     if (parent == NULL)
  277.       return root;
  278.     return adjustAVL(root, parent, child);
  279.   }
  280. }

  281. node* deleteNode(int key, node* root)
  282. {
  283.   node *dNode, *parent, *child, *tp;
  284.   int temp, tc;
  285.   assert(root!=NULL);
  286.   if (!searchNode(key, root, &parent))
  287.     return root;
  288.   else
  289.   {
  290.     if (parent == NULL)
  291.       dNode = root;
  292.     else if ((parent->left!=NULL)&&(parent->left->key==key))
  293.       dNode = parent->left;
  294.     else dNode = parent->right;

  295.     child = dNode;
  296.     while ((child->left!=NULL)||(child->right!=NULL)) //确定需要删除的结点
  297.     {
  298.       if (child->balance == 1)
  299.         child = preNode(dNode);
  300.       else child = nextNode(dNode);
  301.       temp = child->key;
  302.       child->key = dNode->key;
  303.       dNode->key = temp;
  304.       dNode = child;
  305.     }
  306.    
  307.     child = dNode;
  308.     parent = dNode->parent;
  309.       
  310.     while ((parent != NULL)) //查找需要调整的最小子树
  311.     {
  312.       if (child == parent->left)
  313.         if (parent->balance == 1)
  314.         {
  315.           parent->balance = 0;
  316.           child = parent;
  317.           parent = parent->parent;
  318.         }
  319.         else if (parent->balance == -1)
  320.         {
  321.           parent->balance = -2;
  322.           child = parent->right;
  323.           temp = parent->right->balance;//临时变量保存
  324.           tp = parent->parent;//临时变量保存
  325.           if (tp != NULL)
  326.             if (parent == tp->left)
  327.               tc = 1;
  328.             else tc = -1;
  329.           else tc = 0;
  330.          
  331.           root = adjustAVL(root, parent, child);
  332.          
  333.           if (temp == 0)
  334.             break;
  335.           else
  336.           {
  337.             if (tc == 1)
  338.               child = tp->left;
  339.             else if (tc == -1)
  340.               child = tp->right;
  341.             parent = tp;
  342.           }

  343.         }
  344.         else
  345.         {
  346.           parent->balance = -1;
  347.           break;
  348.         }
  349.       else if (parent->balance == -1)
  350.       {
  351.         parent->balance = 0;
  352.         child = parent;
  353.         parent = parent->parent;
  354.       }
  355.       else if (parent->balance == 1)
  356.       {
  357.         parent->balance = 2;
  358.         child = parent->left;
  359.         temp = parent->left->balance;//临时变量保存
  360.         tp = parent->parent;//临时变量保存
  361.         if (tp != NULL)
  362.           if (parent == tp->left)
  363.             tc = 1;
  364.           else tc = -1;
  365.         else tc = 0;
  366.         
  367.         root = adjustAVL(root, parent, child);
  368.         
  369.         if (temp == 0)
  370.           break;
  371.         else
  372.         {
  373.           if (tc == 1)
  374.             child = tp->left;
  375.           else if (tc == -1)
  376.             child = tp->right;
  377.           parent = tp;
  378.         }
  379.       }
  380.       else
  381.       {
  382.         parent->balance = 1;
  383.         break;
  384.       }
  385.     }
  386.    
  387.     if (dNode->parent != NULL)
  388.       if (dNode == dNode->parent->left)
  389.         dNode->parent->left = NULL;
  390.       else dNode->parent->right = NULL;
  391.     free(dNode);
  392.     if (root == dNode)
  393.       root = NULL; //root被删除, 避免野指针
  394.     dNode = NULL;
  395.    
  396.     return root;
  397.   }
  398. }


  399. node* createAVL(int *data, int size)
  400. {
  401.   int i, j;
  402.   node *root;
  403.   if (size<1)
  404.     return NULL;
  405.   root = (node*)malloc(sizeof(node));
  406.   root->parent = NULL;
  407.   root->left = NULL;
  408.   root->right = NULL;
  409.   root->key = data[0];
  410.   root->balance = 0;
  411.   
  412.   for(i=1;i<size;i++)
  413.     root = insertNode(data[i], root);
  414.   return root;
  415. }

  416. void destroyAVL(node* root)
  417. {
  418.   if (root != NULL)
  419.   {
  420.     destroyAVL(root->left);
  421.     destroyAVL(root->right);
  422.     free(root);
  423.     root=NULL;
  424.   }
  425.   
  426. }

  427. void traverseAVL1(node* root) //中序遍历
  428. {
  429.   if (root != NULL)
  430.   {
  431.     traverseAVL1(root->left);
  432.     printf("%d, %d\n", root->key, root->balance);
  433.     traverseAVL1(root->right);
  434.   }
  435. }

  436. void traverseAVL2(node* root) //先序遍历
  437. {
  438.   if (root != NULL)
  439.   {
  440.     printf("%d, %d\n", root->key, root->balance);
  441.     traverseAVL2(root->left);
  442.     traverseAVL2(root->right);
  443.   }
  444. }

  445. int main(int argc, char *argv[])
  446. {
  447.   int data[] = {1, 5, 7, 4, 3, 2, 11, 9, 10};
  448.   node* root;
  449.   root = createAVL(data, sizeof(data)/sizeof(data[0]));

  450.   printf("++++++++++++++++++++++++++++\n");
  451.   traverseAVL1(root);
  452.   printf("\n");
  453.   traverseAVL2(root);
  454.   
  455.   root = deleteNode(5, root);
  456.   printf("++++++++++++++++++++++++++++\n");
  457.   traverseAVL1(root);
  458.   printf("\n");
  459.   traverseAVL2(root);

  460.   root = deleteNode(3, root);
  461.   printf("++++++++++++++++++++++++++++\n");
  462.   traverseAVL1(root);
  463.   printf("\n");
  464.   traverseAVL2(root);

  465.   root = deleteNode(1, root);
  466.   printf("++++++++++++++++++++++++++++\n");
  467.   traverseAVL1(root);
  468.   printf("\n");
  469.   traverseAVL2(root);

  470.   root = deleteNode(7, root);
  471.   printf("++++++++++++++++++++++++++++\n");
  472.   traverseAVL1(root);
  473.   printf("\n");
  474.   traverseAVL2(root);

  475.   root = deleteNode(4, root);
  476.   printf("++++++++++++++++++++++++++++\n");
  477.   traverseAVL1(root);
  478.   printf("\n");
  479.   traverseAVL2(root);

  480.   root = deleteNode(2, root);
  481.   printf("++++++++++++++++++++++++++++\n");
  482.   traverseAVL1(root);
  483.   printf("\n");
  484.   traverseAVL2(root);

  485.   destroyAVL(root);
  486. }

复制代码

[ 本帖最后由 ypxing 于 2007-12-8 12:06 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2007-11-03 21:38 |只看该作者
顶~~~

论坛徽章:
0
3 [报告]
发表于 2007-11-03 21:42 |只看该作者
我也写过一个:
http://www.cppblog.com/converse/archive/2007/08/29/31179.html

细细想来,基本的数据结构除了图没有碰过以外其他都自己动手实践过了

论坛徽章:
0
4 [报告]
发表于 2007-11-03 21:47 |只看该作者
看过你写的红黑树
准备自己也实现一下

原帖由 converse 于 2007-11-3 21:42 发表
我也写过一个:
http://www.cppblog.com/converse/archive/2007/08/29/31179.html

细细想来,基本的数据结构除了图没有碰过以外其他都自己动手实践过了

论坛徽章:
0
5 [报告]
发表于 2007-11-03 21:52 |只看该作者
原帖由 ypxing 于 2007-11-3 21:47 发表
看过你写的红黑树
准备自己也实现一下



最近一直在想AVL树和红黑树效率上到底有什么区别?分别有哪些适用场合...

更让我吐血的是,发明红黑树的哥们是怎么想到这么个鬼东西的

论坛徽章:
0
6 [报告]
发表于 2007-11-03 22:03 |只看该作者
印象里红黑树的应用似乎更广些


原帖由 converse 于 2007-11-3 21:52 发表


最近一直在想AVL树和红黑树效率上到底有什么区别?分别有哪些适用场合...

更让我吐血的是,发明红黑树的哥们是怎么想到这么个鬼东西的

论坛徽章:
0
7 [报告]
发表于 2007-11-03 22:15 |只看该作者
我总觉得红黑树是AVL的特例

论坛徽章:
0
8 [报告]
发表于 2007-11-04 17:32 |只看该作者

回复 #7 converse 的帖子

红黑树不是 AVL 的特例

AVL 的左子树和右子树高度最多相差 1, 而红黑的最长路径可以是最短路径的两倍, AVL 比红黑树要平衡。

AVL 的删除最多需要 O(lg n) 次旋转,而红黑树的删除需要不多于 3 次旋转,但更改颜色次数以 log n 为界。

红黑树的黑点是骨架,限制了整棵树的高度;而红点是肉,可以通过插入红点来把树撑高,但由于两个黑点之间最多有一个红点,所以高度仍受黑点限制。最短的路径上可以全是黑点,而最长的路径上,红点至多能达到黑点数减 1,或者说路径长度是 black height 的两倍。

红黑树其实与 2-3-4 树(一种 B 树)对应,若把黑点的红儿子提上来,并与黑点一起,作为一个大点,就得到了一棵 2-3-4 树,树高就是 black height. 而红黑树的插入、删除与相应的 2-3-4 树的插入删除是可以相互印证的。

[ 本帖最后由 win_hate 于 2007-11-4 17:36 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2007-11-04 17:37 |只看该作者
原帖由 win_hate 于 2007-11-4 17:32 发表
红黑树不是 AVL 的特例

AVL 的左子树和右子树高度最多相差 1, 而红黑的最长路径可以是最短路径的两倍, AVL 比红黑树要平衡。

AVL 的删除最多需要 O(lg n) 次旋转,而红黑树的删除需要不多于 3 次旋转, ...


版主给讲讲红黑树吧,之前看过你的AVL讲解.
我也比较不懂发明红黑树的人是怎么想到的.

论坛徽章:
0
10 [报告]
发表于 2007-11-04 17:50 |只看该作者

回复 #9 baohuaihuai 的帖子

红黑树刚出来的时候不叫红黑树,叫对称二元 B 树, 发明者是 Bayer, 后来 Sedgewick  和另一个不记得是谁把颜色加进去,演化成现在的红黑树。

看他们的文章就可以知道红黑树是怎么演变过来的了。一些算法书的参考文献列出了相关文献。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP