【第十四周项目1 - 验证算法之平衡二叉树】

来源:互联网 发布:淘宝c店的运营案例 编辑:程序博客网 时间:2024/05/21 10:30

问题及代码:


  1. #include <stdio.h>  
  2. #include <malloc.h>  
  3. typedef int KeyType;                    //定义关键字类型  
  4. typedef char InfoType;  
  5. typedef struct node                     //记录类型  
  6. {  
  7.     KeyType key;                        //关键字项  
  8.     int bf;                             //平衡因子  
  9.     InfoType data;                      //其他数据域  
  10.     struct node *lchild,*rchild;        //左右孩子指针  
  11. } BSTNode;  
  12. void LeftProcess(BSTNode *&p,int &taller)  
  13. //对以指针p所指结点为根的二叉树作左平衡旋转处理,本算法结束时,指针p指向新的根结点  
  14. {  
  15.     BSTNode *p1,*p2;  
  16.     if (p->bf==0)           //原本左、右子树等高,现因左子树增高而使树增高  
  17.     {  
  18.         p->bf=1;  
  19.         taller=1;  
  20.     }  
  21.     else if (p->bf==-1)     //原本右子树比左子树高,现左、右子树等高  
  22.     {  
  23.         p->bf=0;  
  24.         taller=0;  
  25.     }  
  26.     else                    //原本左子树比右子树高,需作左子树的平衡处理  
  27.     {  
  28.         p1=p->lchild;       //p指向*p的左子树根结点  
  29.         if (p1->bf==1)      //新结点插入在*b的左孩子的左子树上,要作LL调整  
  30.         {  
  31.             p->lchild=p1->rchild;  
  32.             p1->rchild=p;  
  33.             p->bf=p1->bf=0;  
  34.             p=p1;  
  35.         }  
  36.         else if (p1->bf==-1)    //新结点插入在*b的左孩子的右子树上,要作LR调整  
  37.         {  
  38.             p2=p1->rchild;  
  39.             p1->rchild=p2->lchild;  
  40.             p2->lchild=p1;  
  41.             p->lchild=p2->rchild;  
  42.             p2->rchild=p;  
  43.             if (p2->bf==0)          //新结点插在*p2处作为叶子结点的情况  
  44.                 p->bf=p1->bf=0;  
  45.             else if (p2->bf==1)     //新结点插在*p2的左子树上的情况  
  46.             {  
  47.                 p1->bf=0;  
  48.                 p->bf=-1;  
  49.             }  
  50.             else                    //新结点插在*p2的右子树上的情况  
  51.             {  
  52.                 p1->bf=1;  
  53.                 p->bf=0;  
  54.             }  
  55.             p=p2;  
  56.             p->bf=0;            //仍将p指向新的根结点,并置其bf值为0  
  57.         }  
  58.         taller=0;  
  59.     }  
  60. }  
  61. void RightProcess(BSTNode *&p,int &taller)  
  62. //对以指针p所指结点为根的二叉树作右平衡旋转处理,本算法结束时,指针p指向新的根结点  
  63. {  
  64.     BSTNode *p1,*p2;  
  65.     if (p->bf==0)           //原本左、右子树等高,现因右子树增高而使树增高  
  66.     {  
  67.         p->bf=-1;  
  68.         taller=1;  
  69.     }  
  70.     else if (p->bf==1)      //原本左子树比右子树高,现左、右子树等高  
  71.     {  
  72.         p->bf=0;  
  73.         taller=0;  
  74.     }  
  75.     else                    //原本右子树比左子树高,需作右子树的平衡处理  
  76.     {  
  77.         p1=p->rchild;       //p指向*p的右子树根结点  
  78.         if (p1->bf==-1)     //新结点插入在*b的右孩子的右子树上,要作RR调整  
  79.         {  
  80.             p->rchild=p1->lchild;  
  81.             p1->lchild=p;  
  82.             p->bf=p1->bf=0;  
  83.             p=p1;  
  84.         }  
  85.         else if (p1->bf==1) //新结点插入在*p的右孩子的左子树上,要作RL调整  
  86.         {  
  87.             p2=p1->lchild;  
  88.             p1->lchild=p2->rchild;  
  89.             p2->rchild=p1;  
  90.             p->rchild=p2->lchild;  
  91.             p2->lchild=p;  
  92.             if (p2->bf==0)          //新结点插在*p2处作为叶子结点的情况  
  93.                 p->bf=p1->bf=0;  
  94.             else if (p2->bf==-1)    //新结点插在*p2的右子树上的情况  
  95.             {  
  96.                 p1->bf=0;  
  97.                 p->bf=1;  
  98.             }  
  99.             else                    //新结点插在*p2的左子树上的情况  
  100.             {  
  101.                 p1->bf=-1;  
  102.                 p->bf=0;  
  103.             }  
  104.             p=p2;  
  105.             p->bf=0;            //仍将p指向新的根结点,并置其bf值为0  
  106.         }  
  107.         taller=0;  
  108.     }  
  109. }  
  110. int InsertAVL(BSTNode *&b,KeyType e,int &taller)  
  111. /*若在平衡的二叉排序树b中不存在和e有相同关键字的结点,则插入一个 
  112.   数据元素为e的新结点,并返回1,否则返回0。若因插入而使二叉排序树 
  113.   失去平衡,则作平衡旋转处理,布尔变量taller反映b长高与否*/  
  114. {  
  115.     if(b==NULL)         //原为空树,插入新结点,树“长高”,置taller为1  
  116.     {  
  117.         b=(BSTNode *)malloc(sizeof(BSTNode));  
  118.         b->key=e;  
  119.         b->lchild=b->rchild=NULL;  
  120.         b->bf=0;  
  121.         taller=1;  
  122.     }  
  123.     else  
  124.     {  
  125.         if (e==b->key)              //树中已存在和e有相同关键字的结点则不再插入  
  126.         {  
  127.             taller=0;  
  128.             return 0;  
  129.         }  
  130.         if (e<b->key)               //应继续在*b的左子树中进行搜索  
  131.         {  
  132.             if ((InsertAVL(b->lchild,e,taller))==0) //未插入  
  133.                 return 0;  
  134.             if (taller==1)          //已插入到*b的左子树中且左子树“长高”  
  135.                 LeftProcess(b,taller);  
  136.         }  
  137.         else                        //应继续在*b的右子树中进行搜索  
  138.         {  
  139.             if ((InsertAVL(b->rchild,e,taller))==0) //未插入  
  140.                 return 0;  
  141.             if (taller==1)          //已插入到b的右子树且右子树“长高”  
  142.                 RightProcess(b,taller);  
  143.         }  
  144.     }  
  145.     return 1;  
  146. }  
  147. void DispBSTree(BSTNode *b) //以括号表示法输出AVL  
  148. {  
  149.     if (b!=NULL)  
  150.     {  
  151.         printf("%d",b->key);  
  152.         if (b->lchild!=NULL || b->rchild!=NULL)  
  153.         {  
  154.             printf("(");  
  155.             DispBSTree(b->lchild);  
  156.             if (b->rchild!=NULL) printf(",");  
  157.             DispBSTree(b->rchild);  
  158.             printf(")");  
  159.         }  
  160.     }  
  161. }  
  162. void LeftProcess1(BSTNode *&p,int &taller)  //在删除结点时进行左处理  
  163. {  
  164.     BSTNode *p1,*p2;  
  165.     if (p->bf==1)  
  166.     {  
  167.         p->bf=0;  
  168.         taller=1;  
  169.     }  
  170.     else if (p->bf==0)  
  171.     {  
  172.         p->bf=-1;  
  173.         taller=0;  
  174.     }  
  175.     else        //p->bf=-1  
  176.     {  
  177.         p1=p->rchild;  
  178.         if (p1->bf==0)          //需作RR调整  
  179.         {  
  180.             p->rchild=p1->lchild;  
  181.             p1->lchild=p;  
  182.             p1->bf=1;  
  183.             p->bf=-1;  
  184.             p=p1;  
  185.             taller=0;  
  186.         }  
  187.         else if (p1->bf==-1)    //需作RR调整  
  188.         {  
  189.             p->rchild=p1->lchild;  
  190.             p1->lchild=p;  
  191.             p->bf=p1->bf=0;  
  192.             p=p1;  
  193.             taller=1;  
  194.         }  
  195.         else                    //需作RL调整  
  196.         {  
  197.             p2=p1->lchild;  
  198.             p1->lchild=p2->rchild;  
  199.             p2->rchild=p1;  
  200.             p->rchild=p2->lchild;  
  201.             p2->lchild=p;  
  202.             if (p2->bf==0)  
  203.             {  
  204.                 p->bf=0;  
  205.                 p1->bf=0;  
  206.             }  
  207.             else if (p2->bf==-1)  
  208.             {  
  209.                 p->bf=1;  
  210.                 p1->bf=0;  
  211.             }  
  212.             else  
  213.             {  
  214.                 p->bf=0;  
  215.                 p1->bf=-1;  
  216.             }  
  217.             p2->bf=0;  
  218.             p=p2;  
  219.             taller=1;  
  220.         }  
  221.     }  
  222. }  
  223. void RightProcess1(BSTNode *&p,int &taller) //在删除结点时进行右处理  
  224. {  
  225.     BSTNode *p1,*p2;  
  226.     if (p->bf==-1)  
  227.     {  
  228.         p->bf=0;  
  229.         taller=-1;  
  230.     }  
  231.     else if (p->bf==0)  
  232.     {  
  233.         p->bf=1;  
  234.         taller=0;  
  235.     }  
  236.     else        //p->bf=1  
  237.     {  
  238.         p1=p->lchild;  
  239.         if (p1->bf==0)          //需作LL调整  
  240.         {  
  241.             p->lchild=p1->rchild;  
  242.             p1->rchild=p;  
  243.             p1->bf=-1;  
  244.             p->bf=1;  
  245.             p=p1;  
  246.             taller=0;  
  247.         }  
  248.         else if (p1->bf==1)     //需作LL调整  
  249.         {  
  250.             p->lchild=p1->rchild;  
  251.             p1->rchild=p;  
  252.             p->bf=p1->bf=0;  
  253.             p=p1;  
  254.             taller=1;  
  255.         }  
  256.         else                    //需作LR调整  
  257.         {  
  258.             p2=p1->rchild;  
  259.             p1->rchild=p2->lchild;  
  260.             p2->lchild=p1;  
  261.             p->lchild=p2->rchild;  
  262.             p2->rchild=p;  
  263.             if (p2->bf==0)  
  264.             {  
  265.                 p->bf=0;  
  266.                 p1->bf=0;  
  267.             }  
  268.             else if (p2->bf==1)  
  269.             {  
  270.                 p->bf=-1;  
  271.                 p1->bf=0;  
  272.             }  
  273.             else  
  274.             {  
  275.                 p->bf=0;  
  276.                 p1->bf=1;  
  277.             }  
  278.             p2->bf=0;  
  279.             p=p2;  
  280.             taller=1;  
  281.         }  
  282.     }  
  283. }  
  284. void Delete2(BSTNode *q,BSTNode *&r,int &taller)  
  285. //由DeleteAVL()调用,用于处理被删结点左右子树均不空的情况  
  286. {  
  287.     if (r->rchild==NULL)  
  288.     {  
  289.         q->key=r->key;  
  290.         q=r;  
  291.         r=r->lchild;  
  292.         free(q);  
  293.         taller=1;  
  294.     }  
  295.     else  
  296.     {  
  297.         Delete2(q,r->rchild,taller);  
  298.         if (taller==1)  
  299.             RightProcess1(r,taller);  
  300.     }  
  301. }  
  302. int DeleteAVL(BSTNode *&p,KeyType x,int &taller) //在AVL树p中删除关键字为x的结点  
  303. {  
  304.     int k;  
  305.     BSTNode *q;  
  306.     if (p==NULL)  
  307.         return 0;  
  308.     else if (x<p->key)  
  309.     {  
  310.         k=DeleteAVL(p->lchild,x,taller);  
  311.         if (taller==1)  
  312.             LeftProcess1(p,taller);  
  313.         return k;  
  314.     }  
  315.     else if (x>p->key)  
  316.     {  
  317.         k=DeleteAVL(p->rchild,x,taller);  
  318.         if (taller==1)  
  319.             RightProcess1(p,taller);  
  320.         return k;  
  321.     }  
  322.     else            //找到了关键字为x的结点,由p指向它  
  323.     {  
  324.         q=p;  
  325.         if (p->rchild==NULL)        //被删结点右子树为空  
  326.         {  
  327.             p=p->lchild;  
  328.             free(q);  
  329.             taller=1;  
  330.         }  
  331.         else if (p->lchild==NULL)   //被删结点左子树为空  
  332.         {  
  333.             p=p->rchild;  
  334.             free(q);  
  335.             taller=1;  
  336.         }  
  337.         else                        //被删结点左右子树均不空  
  338.         {  
  339.             Delete2(q,q->lchild,taller);  
  340.             if (taller==1)  
  341.                 LeftProcess1(q,taller);  
  342.             p=q;  
  343.         }  
  344.         return 1;  
  345.     }  
  346. }  
  347. int main()  
  348. {  
  349.     BSTNode *b=NULL;  
  350.     int i,j,k;  
  351.     KeyType a[]= {16,3,7,11,9,26,18,14,15},n=9; //例10.5  
  352.     printf(" 创建一棵AVL树:\n");  
  353.     for(i=0; i<n; i++)  
  354.     {  
  355.         printf("   第%d步,插入%d元素:",i+1,a[i]);  
  356.         InsertAVL(b,a[i],j);  
  357.         DispBSTree(b);  
  358.         printf("\n");  
  359.     }  
  360.     printf("   AVL:");  
  361.     DispBSTree(b);  
  362.     printf("\n");  
  363.     printf(" 删除结点:\n");                     //例10.6  
  364.     k=11;  
  365.     printf("   删除结点%d:",k);  
  366.     DeleteAVL(b,k,j);  
  367.     printf("   AVL:");  
  368.     DispBSTree(b);  
  369.     printf("\n");  
  370.     k=9;  
  371.     printf("   删除结点%d:",k);  
  372.     DeleteAVL(b,k,j);  
  373.     printf("   AVL:");  
  374.     DispBSTree(b);  
  375.     printf("\n");  
  376.     k=15;  
  377.     printf("   删除结点%d:",k);  
  378.     DeleteAVL(b,k,j);  
  379.     printf("   AVL:");  
  380.     DispBSTree(b);  
  381.     printf("\n\n");  
  382.     return 0;  
  383. }  

运行结果:



知识点总结:

平衡二叉树的相关算法


学习心得:

平衡二叉树是很重要的 


原文出处:http://blog.csdn.net/dlkfjdfj/article/details/53432477

0 0
原创粉丝点击