• 12 二叉树-链式存储-二叉排序树(BST)


    呜呜 写这个东西花了我2天 居然花了两天!!我还要写AVL呢啊啊啊啊啊啊啊!!!!!!

    等下还要跑去上自习 大早上起来脸都没洗现在先赶紧发博客 昨晚写出来了独自在其他人都睡着了的宿舍狂喜乱舞。。

    迷之想哭 不知道能不能考上。。。。。。

    不管能不能考上 活在当下就对了 走好每一步踏踏实实吧!!

    删除操作的代码考虑了很多东西,自己写的时候一开始觉得有点抽象,特别是左右孩子链接的处理,还有是否是根结点的判别……

    其实也不知道我这个写法对不对,看了一些网上的代码,别人的都写得好简单啊!

    先这么写着吧,回头有空了我再思考下有没有更简单的实现方法!如果有网友有好建议也欢迎留言!


    1、二叉排序树的定义:

     或者是一棵空树,或者是一颗具有以下特性的非空二叉树:

    (1)若左(右)子树非空,则右(左)子树上的关键字值均小(大)于根结点的关键字值。

    (2)左、右子树本身也分别是一颗二叉树。

    2、二叉排序树的特点:

    (1)对二叉排序树进行中序遍历可以得到一个递增的有序序列。

    (2)维护的时候只需修改指针就可以完成插入和删除操作,平均执行时间为O(log2n)。

    (3)平均查找性能取决于树的高度,最糟糕的情况下:由于输入的序列是有序的,形成了倾斜单支二叉树(可以理解为变成一个单链表),查找效率降成O(n)(平均查找长度与单链表相同)。

    (4)查找判定树不唯一。

    3、二叉排序树的适用场合:

    有序表是动态查找表的时候应选择二叉排序树作为其逻辑结构。(静态查找表则合适用顺序表)


    4、代码实现

    注释详见代码!这里不赘述了!如果有不明白或者有错的地方欢迎留言和指正!

    包括:

    ①二叉排序树的建立(包含插入操作)

    ②二叉排序树的查找

    ③二叉排序树的删除

    ④为了写删除操作还增加了一个判别孩子结点是双亲结点的左孩子or右孩子的小函数……

    【注】因为此代码算法是自己思考设计的,自己比较笨拙,可能会有实现很冗余的地方,如果要使用建议参考其他人的版本。。可能只合适做数据结构的学习理解用orz

      1 #include<iostream>
      2 #include<stdlib.h>
      3 #include<cstdio>
      4 #include<stack>
      5 #include<queue>
      6 using namespace std;
      7 #define TRUE 1
      8 #define FALSE 0
      9 #define OK 1
     10 #define ERROR 0
     11 #define OVERFLOW -2
     12 typedef int Status;
     13 typedef int ElemType;
     14 /*存储结构描述*/
     15 typedef struct BitNode
     16 {
     17     int data;
     18     struct BitNode *lchild,*rchild;
     19 } BitNode,*BiTree;
     20 /*建立一个二叉排序树*/
     21 /*其实是二叉排序树的插入算法*/
     22 void initTree(BiTree &T,int x)
     23 {
     24     if(T==NULL)
     25     {
     26         T=(BitNode*)malloc(sizeof(BitNode));
     27         T->data=x;
     28         T->lchild=NULL;
     29         T->rchild=NULL;
     30     }
     31     else
     32     {
     33         if(x>T->data)
     34             initTree(T->rchild,x);
     35         else initTree(T->lchild,x);
     36     }
     37 }
     38 /*二叉排序树的结点查找*/
     39 /*
     40 1、如果查找成功,返回查找的结点
     41 2、如果查找失败 返回NULL(走到了叶子结点的下一层→【NULL】)
     42 3、指针p指向结点的双亲结点
     43 */
     44 BitNode *BST_Search(BiTree T,int x,BitNode *&p)
     45 {
     46 
     47     p=NULL;
     48     while(T!=NULL&&x!=T->data)
     49     {
     50         p=T;
     51         if(x<T->data)
     52             T=T->lchild;
     53         else T=T->rchild;
     54     }
     55     return T;
     56 }
     57 /*结点的删除*/
     58 /*
     59 1、如果是叶结点,直接删除即可
     60 2、如果删除的结点只有单枝左子树或者右子树→让子树成为父结点的子树,直接替代被删结点的位置
     61 3、如果删除的结点有左右两棵子树,这里可以采用p的(x序遍历)直接后继或者直接前驱进行替代。
     62    这里选为中序遍历的直接后继作为替代结点,其中序遍历下的直接后继为被删除结点右子树最左结点。
     63 4、在最后链接被删结点双亲和被删结点孩子的这一步中,如果被删结点为根结点,则不需修改它双亲结点(本来就没双亲),但是要修改指向树的指针T!!不然它会指向空域。
     64 */
     65 int relationship(BitNode *a,BitNode *b)
     66 {
     67     if(a->lchild==b) return 1;//b是a的左孩子
     68     else if(a->rchild==b) return 2;//b是a的右孩子
     69     else return 3;//没关系
     70 }
     71 
     72 int Delete(BiTree &T,int x)
     73 {
     74     BitNode *p=NULL,*psdad=NULL;
     75     BitNode *tool=NULL,*tooldad=NULL;
     76     p=BST_Search(T,x,psdad);
     77     //如果删除的结点是叶结点
     78     if(p->lchild==NULL&&p->rchild==NULL)
     79     {
     80         if(relationship(psdad,p)==1)
     81         {
     82             psdad->lchild=NULL;
     83         }
     84         else
     85         {
     86             psdad->rchild=NULL;
     87         }
     88         free(p);
     89     }
     90     else if(p->lchild==NULL)
     91     {
     92         if(relationship(psdad,p)==1)
     93         {
     94             psdad->lchild=p->rchild;
     95             free(p);
     96         }
     97         else
     98         {
     99             psdad->rchild=p->rchild;
    100             free(p);
    101         }
    102     }
    103     else if(p->rchild==NULL)
    104     {
    105         if(relationship(psdad,p)==1)
    106         {
    107             psdad->lchild=p->lchild;
    108             free(p);
    109         }
    110         else
    111         {
    112             psdad->rchild=p->lchild;
    113             free(p);
    114         }
    115     }
    116     else//p有左右两棵子树//有错,明天思考
    117     {
    118         tooldad=p;
    119         tool=p->rchild;
    120         /*转向右子树,向左走到尽头*/
    121         //cout<<"tool1:"<<tool->data<<endl;
    122         //if(tooldad!=NULL)
    123         //    cout<<"tooldad:"<<tooldad->data<<endl;
    124         //else cout<<"tooldad:null"<<endl;
    125 
    126         while(tool->lchild)
    127         {
    128             tooldad=tool;
    129             tool=tool->lchild;
    130         }
    131 
    132         //cout<<"tool2:"<<tool->data<<endl;
    133         //if(tooldad!=NULL)
    134           //  cout<<"tooldad:"<<tooldad->data<<endl;
    135         //else cout<<"tooldad:null"<<endl;
    136         if(tool==p->rchild)//即:被删除结点右子树的中序遍历第一个结点就是右孩子,这时直接把右孩子挪上去代替被删结点
    137         {
    138             //cout<<"ct1"<<endl;
    139             tool->lchild=p->lchild;
    140             if(psdad)//如果被删除的不是根结点 则需要把代替原位置的结点和被删结点的双亲接连上去
    141             {
    142                 if(relationship(psdad,p)==1)
    143                 {
    144                     psdad->lchild=tool;
    145                     free(p);
    146                 }
    147                 else
    148                 {
    149                     psdad->rchild=tool;
    150                     free(p);
    151                 }
    152             }
    153             else//被删除的是根结点 要把指向根结点的指针一并修改 不然树头会指向空域
    154             {T=tool;free(p);}
    155         }
    156         else
    157         {
    158             //cout<<"ct2"<<endl;
    159             tooldad->lchild=tool->rchild;//当前结点为最左结点,它一定没有左孩子,可能有右孩子。
    160             tool->lchild=p->lchild;
    161             tool->rchild=p->rchild;
    162             tool->lchild=p->lchild;
    163             if(psdad)
    164             {
    165                 if(relationship(psdad,p)==1)
    166                 {
    167                     psdad->lchild=tool;
    168                     free(p);
    169                 }
    170                 else
    171                 {
    172                     psdad->rchild=tool;
    173                     free(p);
    174                 }
    175             }
    176             else {T=tool;free(p);}
    177         }
    178     }
    179     return OK;
    180 
    181 }
    182 
    183 void visit(BiTree T)
    184 {
    185     cout<<T->data<<' ';
    186 }
    187 /*中序遍历测试用*/
    188 void inOrder(BiTree T)
    189 {
    190     if(T!=NULL)
    191     {
    192         inOrder(T->lchild);
    193         visit(T);
    194         inOrder(T->rchild);
    195     }
    196 }
    197 int main()
    198 {
    199     BiTree tree=NULL;
    200     BitNode *ans=NULL,*ansdad=NULL;
    201     int x;
    202     cin>>x;
    203     while(x!=0)
    204     {
    205         initTree(tree,x);
    206         cin>>x;
    207     }
    208     cout<<"--- show the bst tree ---"<<endl;
    209     inOrder(tree);
    210     cout<<endl;
    211     cout<<"Test Search function:"<<endl;
    212     cin>>x;
    213     ans=BST_Search(tree,x,ansdad);
    214     if(ans==NULL)
    215         cout<<"NULL."<<endl;
    216     else
    217     {
    218         cout<<"successful found."<<ans->data<<endl;
    219         if(ansdad!=NULL)
    220             cout<<"His father's data is:"<<ansdad->data<<endl;
    221         else cout<<"He is the Root of BST tree."<<endl;
    222     }
    223     int w;
    224 
    225     cin>>w;
    226     while(w!=0)
    227     {
    228         Delete(tree,w);
    229         cout<<"--- show the bst tree ---"<<endl;
    230         inOrder(tree);
    231         cout<<endl;
    232         cin>>w;
    233     }
    234     return 0;
    235 }

    5、代码实现截图

  • 相关阅读:
    Android画图最基本的三个对象(Color,Paint,Canvas)
    搭建Android开发环境之旅
    对象序列化与反序列化
    JUnit 3.8 演示递归删除文件目录的 测试类程序 .
    JUnit 3.8 让所有测试程序 实现 复合的测试(TestSuite)
    JUnit 3.8 通过反射测试私有方法
    Java NIO
    Java泛型 类型变量的限定
    组织领导层在信息化建设中须要解决的问题
    bootstrap之鼠标操作
  • 原文地址:https://www.cnblogs.com/AKsnoopy/p/7513126.html
Copyright © 2020-2023  润新知