免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: augustusqing
打印 上一主题 下一主题

[算法] 求AVL平衡树删除操作的过程分析和实例程序 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2007-12-07 15:29 |只看该作者

回复 #7 anthony1983 的帖子

哈哈,多谢“看好”,^_^

原帖由 Sorehead 于 2007-12-7 11:06 发表
由于工作需要,这段时间一直在接触AVL树,不过需求是需要插入,不用删除,所以对删除操作也不是非常熟悉。
不过查过一些删除方面的资料,了解一些,删除其实并不比插入难多少,只要真正理解了插入是怎么一回事 ...

哈哈,确实如你所说,现在发现删除操作与插入操作很比较对称的,
用递规版本实现代码,删除操作的代码与插入代码很相似,就是在平衡处理中要多添加一种情况,因为平衡操作后,仍然可能变短了,需要上一层继续平衡处理

论坛徽章:
0
12 [报告]
发表于 2007-12-07 16:03 |只看该作者

回复 #10 lucency 的帖子

多谢你的分析,我差不多是按你的思路来的,先找到相应节点,如果它本来就是叶子节点,就删除它,不是,就找它的后继节点代替,保证删除的始终是叶子节点,唯一的例外是只有两个节点的时候,一个根节点,一个左儿子节点,这个例外,我的代码中处理了

我是看到下面这篇文章
http://blog.csdn.net/happycock/archive/2003/08/15/20874.aspx
文章前面没怎么看,但最后面说删除操作和插入操作是对称的,给了我很大鼓舞
然后我就画图,把删除操作过程中与插入过程不同的地方分析出来了,确实删除操作其实没有所谓的很“复杂”,没有比插入复杂很“多”,只是多了几种情况,代码中处理后,就可以了,下面是代码了

采用的是C++实现的,因为节点里没有用父指针,那么在旋转操作中,就必须用二级指针,所以就用了C++的引用,又由于没有父指针,中序遍历的前趋和后继操作没有实现,对于这两个操作,我现在只会实现有父指针的,^_^

文件: include/Item.h

  1. /*-----------------------------------------------------------
  2.         Item.h
  3.         Author: QingXiaoming, 12-06, 2007([url]http://www.cublog.com/augustusqing/[/url]
  4.        您可以自由拷贝,修改,分发这份代码,但请注明原作者
  5. -------------------------------------------------------------*/

  6. #ifndef ITEM_H
  7. #define ITEM_H

  8. typedef int Item;

  9. #endif
复制代码

文件:include/AVL_ADT.h

  1. /*-----------------------------------------------------------
  2.         AVL的ADT接口
  3.         Author: QingXiaoming, 12-06, 2007([url]http://www.cublog.com/augustusqing/[/url]
  4.        您可以自由拷贝,修改,分发这份代码,但请注明原作者
  5. -------------------------------------------------------------*/
  6. #ifndef AVL_ADT_H
  7. #define AVL_ADT_H

  8. #include "Item.h"

  9. typedef struct AVLNode *AVLTree;

  10. AVLTree initAVL(void);
  11. int emptyAVL(AVLTree);
  12. void pretravseAVL(AVLTree);
  13. void midtravseAVL(AVLTree);
  14. Item minAVL(AVLTree);
  15. Item maxAVL(AVLTree);
  16. AVLTree findAVL(AVLTree, Item);
  17. Item preAVL(AVLTree, Item);
  18. Item sucAVL(AVLTree, Item);
  19. int insertAVL(AVLTree &, Item, int &);
  20. int deleteAVL(AVLTree &, Item);
  21. void destroyAVL(AVLTree &);

  22. #endif
复制代码

论坛徽章:
0
13 [报告]
发表于 2007-12-07 16:05 |只看该作者
文件:AVL_ADT.c

  1. /*-----------------------------------------------------------
  2.         AVL的ADT实现
  3.      Author: QingXiaoming, 12-06, 2007([url]http://www.cublog.com/augustusqing/[/url]
  4.        您可以自由拷贝,修改,分发这份代码,但请注明原作者
  5. -------------------------------------------------------------*/
  6. #include <iostream>
  7. #include <cstdlib>
  8. #include "include/AVL_ADT.h"

  9. #define EH 0
  10. #define LH 1
  11. #define RH -1
  12. #define TRUE 1
  13. #define FALSE 0

  14. struct AVLNode {
  15.        public:
  16.               AVLNode(Item);
  17.                Item item;
  18.                AVLTree lchild;
  19.                AVLTree rchild;
  20.                int bh;
  21.        };
  22. AVLNode::AVLNode(Item t)
  23. {
  24.     item = t;bh = EH;
  25.     lchild = rchild = NULL;
  26. }

  27. static void showAVLTreeNode(AVLTree tree);
  28. static void Left_Rotate(AVLTree & tree);
  29. static void Right_Rotate(AVLTree & tree);
  30. static int Left_Balance(AVLTree & tree);
  31. static int Right_Balance(AVLTree & tree);
  32. static int deleteavl(AVLTree & tree, AVLTree link, int & shorter);
  33. static AVLTree deleteAVLNode(AVLTree & tree, Item item);

  34. AVLTree initAVL()
  35. {
  36.     return NULL;
  37. }

  38. int emptyAVL(AVLTree tree)
  39. {
  40.     return tree == NULL;
  41. }
  42. inline static void showAVLTreeNode(AVLTree tree)
  43. {
  44.        Item t;
  45.        std::cout << "Item: " << tree->item <<  " BH: " <<  tree->bh << " ";
  46.        if (NULL == tree->lchild && NULL == tree->rchild)
  47.        {
  48.            std::cout << std::endl;
  49.            return;
  50.        }
  51.        if (tree->lchild )
  52.        {
  53.            t = tree->lchild->item;
  54.            std::cout <<  " Lchild: " << t << " ";
  55.        }
  56.        if (tree->rchild)
  57.        {
  58.            t = tree->rchild->item;
  59.            std::cout <<  " Rchild: " << t << " " << std::endl;
  60.        }
  61.        else
  62.        {
  63.            std::cout << std::endl;
  64.        }
  65. }

  66. void pretravseAVL(AVLTree tree)
  67. {
  68.      if (tree)
  69.      {
  70.               showAVLTreeNode(tree);
  71.               pretravseAVL(tree->lchild);
  72.               pretravseAVL(tree->rchild);
  73.      }
  74. }

  75. void midtravseAVL(AVLTree tree)
  76. {
  77.      if (tree)
  78.      {
  79.               midtravseAVL(tree->lchild);
  80.               showAVLTreeNode(tree);
  81.               midtravseAVL(tree->rchild);
  82.      }
  83. }

  84. Item minAVL(AVLTree tree)
  85. {
  86.      if (tree)
  87.      {
  88.               while (tree->lchild)
  89.               {
  90.                     tree = tree->lchild;
  91.               }
  92.               return tree->item;
  93.      }
  94.      else  return -1;
  95. }

  96. Item maxAVL(AVLTree tree)
  97. {
  98.      if (tree)
  99.      {
  100.               while (tree->rchild)
  101.               {
  102.                     tree = tree->rchild;
  103.               }
  104.               return tree->item;
  105.      }
  106.      else  return -1;
  107. }

  108. AVLTree findAVL(AVLTree tree, Item item)
  109. {
  110.     while (NULL != tree && item != tree->item)
  111.     {
  112.           tree = (item < tree->item) ? tree->lchild : tree->rchild;
  113.     }
  114.     return tree;
  115. }

  116. int insertAVL(AVLTree & tree, Item item, int &taller)
  117. {
  118.     int tall;
  119.     taller = FALSE;//also should give the default value
  120.     if (!tree)
  121.     {
  122.         tree = new AVLNode(item);
  123.         taller = TRUE;
  124.         return 1;
  125.     }
  126.     if (item == tree->item)
  127.     {
  128.              taller = FALSE; return 0;
  129.     }
  130.     else if (item < tree->item)
  131.     {
  132.         if (!insertAVL(tree->lchild, item, tall)) return 0;
  133.         if (tall)
  134.         {
  135.             switch (tree->bh)
  136.             {
  137.                   case EH:
  138.                        taller = TRUE;  tree->bh = LH;      break;
  139.                   case RH:
  140.                        taller = FALSE; tree->bh = EH;      break;
  141.                   case LH:
  142.                        taller = FALSE; Left_Balance(tree); break;
  143.             }
  144.         }
  145.     }
  146.     else
  147.     {
  148.         if (!insertAVL(tree->rchild, item, tall)) return 0;
  149.         if (tall)
  150.         {
  151.               switch (tree->bh)
  152.             {
  153.                   case EH:
  154.                        taller = TRUE;  tree->bh = RH;       break;
  155.                   case LH:
  156.                        taller = FALSE; tree->bh = EH;       break;
  157.                   case RH:
  158.                        taller = FALSE; Right_Balance(tree); break;
  159.             }     
  160.         }
  161.     }
  162.     return 1;
  163. }
  164. static void Left_Rotate(AVLTree & tree)
  165. {
  166.        assert(NULL != tree->rchild);//assert to assure the valid
  167.        AVLTree rc = tree->rchild;
  168.        tree->rchild = rc->lchild;
  169.        rc->lchild = tree;
  170.        tree = rc;
  171. }

  172. static void Right_Rotate(AVLTree & tree)
  173. {
  174.        assert(NULL != tree->lchild);//assert to assure the valid
  175.        AVLTree lc = tree->lchild;
  176.        tree->lchild = lc->rchild;
  177.        lc->rchild = tree;
  178.        tree = lc;
  179. }

  180. static int Left_Balance(AVLTree & tree)
  181. {
  182.     int shorter;//this just for delete action, to tell the delete action whether this balance action shotter
  183.     assert(NULL != tree && NULL != tree->lchild);//assert to assure the valid
  184.     AVLTree lc = tree->lchild, rd;
  185.     switch (lc->bh)
  186.     {
  187.           case LH:
  188.                lc->bh = EH; tree->bh = EH;
  189.                Right_Rotate(tree);
  190.                shorter = 1;
  191.                break;
  192.           case RH:
  193.                rd = lc->rchild;
  194.                switch (rd->bh)
  195.                {
  196.                      case EH:
  197.                           tree->bh = EH; lc->bh = EH;
  198.                           break;
  199.                      case LH:
  200.                           tree->bh = RH; lc->bh = EH;
  201.                           break;
  202.                      case RH:
  203.                           tree->bh = EH; lc->bh = LH;
  204.                           break;      
  205.                }
  206.                rd->bh = EH;
  207.                Left_Rotate(tree->lchild);
  208.                Right_Rotate(tree);
  209.                shorter = 1;
  210.                break;
  211.           /*
  212.           when insert , this case will not be ture, it just for delete action
  213.           */
  214.           case EH:
  215.                lc->bh = RH; tree->bh = LH;
  216.                Right_Rotate(tree);
  217.                shorter = 0;
  218.                break;
  219.     }
  220.     return shorter;
  221. }
  222. static int Right_Balance(AVLTree & tree)
  223. {
  224.     int shorter;//this just for delete action, to tell the delete action whether this balance action shotter
  225.     assert(NULL != tree && NULL != tree->rchild);//assert to assure the valid
  226.     AVLTree rc = tree->rchild, ld;
  227.     switch (rc->bh)
  228.     {
  229.           case RH:
  230.                rc->bh = EH; tree->bh = EH; shorter = 1;
  231.                Left_Rotate(tree);
  232.                break;
  233.           case LH:
  234.                ld = rc->lchild;
  235.                switch (ld->bh)
  236.                {
  237.                      case EH:
  238.                           tree->bh = EH; rc->bh = EH;
  239.                           break;
  240.                      case LH:
  241.                           tree->bh = EH; rc->bh = RH;
  242.                           break;
  243.                      case RH:
  244.                           tree->bh = LH; rc->bh = EH;
  245.                           break;      
  246.                }
  247.                ld->bh = EH;
  248.                Right_Rotate(tree->rchild);
  249.                Left_Rotate(tree);
  250.                shorter = 1;
  251.                break;
  252.           /*
  253.           when insert , this case will not be ture, it just for delete action
  254.           */
  255.           case EH:
  256.                rc->bh = LH; tree->bh = RH;
  257.                Left_Rotate(tree);
  258.                shorter = 0;
  259.                break;
  260.     }
  261.     return shorter;
  262. }
  263. static int deleteavl(AVLTree & tree, AVLTree link, int & shorter)
  264. {
  265.        int sht;
  266.        shorter = FALSE;//forget give this default value  
  267.        //case: only two node, root and his lchild, delete the root node
  268.        //Only this case, the link will not be a leaves node
  269.        if (link == tree && tree->lchild)
  270.        {
  271.            tree = link->lchild;
  272.            shorter = TRUE;
  273.            return 1;
  274.        }
  275.        if (link == tree)
  276.        {
  277.            tree = link->rchild;
  278.            shorter = TRUE;
  279.            return 1;
  280.        }
  281.       
  282.        if (link->item < tree->item)
  283.        {
  284.            deleteavl(tree->lchild, link, sht);
  285.            if (sht)
  286.            {
  287.                switch (tree->bh)
  288.                {
  289.                       case EH:
  290.                            tree->bh = RH; shorter = FALSE; break;
  291.                       case LH:
  292.                            tree->bh = EH; shorter = TRUE; break;
  293.                       case RH:
  294.                            shorter = Right_Balance(tree); break;
  295.                }
  296.            }
  297.        }
  298.        else
  299.        {
  300.            deleteavl(tree->rchild, link, sht);
  301.            if (sht)
  302.            {
  303.                switch (tree->bh)
  304.                {
  305.                       case EH:
  306.                            tree->bh = LH; shorter = FALSE; break;
  307.                       case RH:
  308.                            tree->bh = EH; shorter = TRUE; break;
  309.                       case LH:
  310.                            shorter = Left_Balance(tree); break;
  311.                }
  312.            }
  313.        }
  314.        return 1;
  315. }

  316. static AVLTree deleteAVLNode(AVLTree & tree, Item item)
  317. {
  318.         int shorter;
  319.         Item t;
  320.         AVLTree y, x = findAVL(tree, item);
  321.         if (!x){std::cerr << "Cant delete Non Exist Node from a AVL Tree" << std::endl;return NULL;}
  322.         if (x->rchild)
  323.         {
  324.             y = x->rchild;
  325.             while (y->lchild)
  326.             {
  327.                   y = y->lchild;
  328.             }
  329.         }
  330.         else
  331.         {
  332.             y = x;
  333.         }
  334.         deleteavl(tree, y, shorter);
  335.         if (y != x)
  336.         {
  337.             t = x->item; x->item = y->item; y->item = t;
  338.         }
  339.         return y;
  340. }

  341. int deleteAVL(AVLTree & tree, Item item)
  342. {
  343.      AVLTree x = deleteAVLNode(tree, item);
  344.      if (x)
  345.      {
  346.         delete x;
  347.         return 1;
  348.      }
  349.      else
  350.      {
  351.          return 0;
  352.      }
  353. }

  354. void destroyAVL(AVLTree & tree)
  355. {
  356.      Item min = minAVL(tree);
  357.      AVLTree x;
  358.      while (!emptyAVL(tree))
  359.      {
  360.            x = deleteAVLNode(tree, min);
  361.            showAVLTreeNode(x);
  362.            delete x;
  363.            min = minAVL(tree);
  364.      }
  365. }

复制代码


文件: AVL_ADT_user.c

  1. /*-----------------------------------------------------------
  2.         AVL的ADT用户程序
  3.         Author: QingXiaoming, 12-06, 2007([url]http://www.cublog.com/augustusqing/[/url]
  4.        您可以自由拷贝,修改,分发这份代码,但请注明原作者
  5. -------------------------------------------------------------*/
  6. #include <iostream>
  7. #include "include/AVL_ADT.h"

  8. int main(int argc, char *argv[])
  9. {
  10.     int i, N = atoi(argv[1]);
  11.     Item t;
  12.     int taller;
  13.     long start, stop;
  14.     //AVLTree x  = NULL;
  15.     AVLTree tree = initAVL();
  16.     int *a = new int[N];
  17.     start = clock();
  18.     for (i = 0; i < N; i++)
  19.     {
  20.         t = rand();
  21.         a[i] = t;
  22.         //std::cout << t << std::endl;
  23.         insertAVL(tree, t, taller);
  24.     }
  25.     //pretravseAVL(tree);
  26.     //std::cout << std::endl;
  27.     //midtravseAVL(tree);
  28.     std::cout << std::endl;
  29.   
  30.     for (i = 0; i < N; i++)
  31.     {
  32.         t = a[i];
  33.         //std::cout << t << std::endl;
  34.         //pretravseAVL(tree);
  35.         //std::cout << std::endl;
  36.         deleteAVL(tree, t);
  37.         //midtravseAVL(tree);
  38.         //std::cout << std::endl;
  39.     }
  40.     //std::cout << "Tree state " << emptyAVL(tree) << std::endl;
  41.     destroyAVL(tree);
  42.     std::cout << "Tree state " << emptyAVL(tree) << std::endl;
  43.     stop = clock();
  44.     std::cout << stop - start << std::endl;
  45.     delete []a;
  46.     return 0;
  47. }

复制代码

论坛徽章:
0
14 [报告]
发表于 2007-12-07 16:51 |只看该作者

回复 #10 lucency 的帖子

好强的模板功底!
拜读。。。。。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP