zoukankan      html  css  js  c++  java
  • 二叉排序树

    二叉排序树

    二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:

    1)若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;

    2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;

    3)左、右子树也分别为二叉排序树;

     

           I.建树:

           初始时树为空。

    对于第一个数,直接作为树的根结点。

           对于堆中的一个数,起始时设置与之比较的结点为树的根结点,该数与结点的值比较,若该数与结点的值相等,则无操作,结束;若该数比结点的值小,则结点变为结点的左子结点;若该数比结点的值大或等于(其它情况),则结点变为结点的右子结点。直到结点为空,则增加一个结点,为之前结点的左/右子结点,并写入数值。

           II.判断是否出现:

           对于一个需要判断的数,起始时设置与之比较的结点为树的根结点,该数与结点的值比较,若该数与结点的值相等,则该数在堆中出现,结束比较;若该数比结点的值小,则结点变为结点的左子结点;若该数比结点的值大,则结点变为结点的右子结点。直到结点为空,则该数在堆中没有出现,结束比较。

        III.输出:

    任意一个结点,左子结点(如果有)的值小于等于该结点的值,右子结点(如果有)的值大于等于该结点的值。

        所以采用中序遍历(LDR),对于任意一个结点,输出的先后顺序(不一定相邻)为左子结点,根结点,右子结点。

     

    建树保证满足二叉排序树 “对于树中的任意一个结点,若该结点有左子结点,则左子结点的值小于等于该结点的值,若该结点有右子结点,则右子结点的值大于等于该结点的值” 的性质:

    新加入的数满足上述条件,而其它数没有变化,也满足上述条件。所以所有的点满足上述条件。

     

     

           建树和输出的时间复杂度都大约为树所有结点的高度之和。而当树满足线性结构时(内部结点的出度都为1),可用归纳假设证明树所有结点的高度之和最大。

    1.结点为0的树满足当满足线性结构时,树所有结点的高度之和最大;

    2.假设一棵结点数目为n的树,当满足线性结构时,树所有结点的高度之和最大。对于一棵结点数目为n的树增加一个结点,增加的结点高度最大为n,当树满足线性结构时成立。所以一棵结点数目为n+1的树,当满足线性结构时,树所有结点的高度之和最大。

    所以得证。

     

     

    建树+输出的最坏时间复杂度:

    把数按照从小到大或从大到小的顺序加入树中,每次新的结点是上次结点的左/右子结点。树的深度为树所有结点的高度之和,大约为n*n/2,即建树和输出的时间复杂度都为O(n*n/2),总的时间复杂度为O(n*n)。

     

    建树+输出的平均复杂度:O(nlogn)

     

    判断是否出现平均时间复杂度:O(logn),最坏时间复杂度:O(n)。

     

     Code:

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <malloc.h>
      4 
      5 //二叉排序树(判断一个数是否出现在一个序列中)
      6 //1.排序:相同的数要加进去
      7 //2.判断某些数是否在一个序列中
      8 //所以当序列加入二叉排序树中,相同的数不必加入
      9 //但是相同的数不必再加入:需要每次都判断两个数是否相同,时间消耗长,反不如让相同的数也加入树中(如果序列中的数基本不相同)
     10 
     11 struct node
     12 {
     13     long d;
     14     struct node *left;
     15     struct node *right;
     16 }*tree;
     17 
     18 void LDR(struct node *p)
     19 {
     20     if (p!=NULL)
     21     {
     22         LDR(p->left);
     23         printf("%ld ",p->d);
     24         LDR(p->right);
     25     }
     26 }
     27 
     28 int main()
     29 {
     30     struct node *p,*q;
     31     long n,m,s,i;
     32     scanf("%ld",&n);
     33     if (n>=1)
     34     {
     35         scanf("%ld",&s);
     36         tree=(struct node *) malloc (sizeof(struct node));
     37         tree->d=s;
     38         tree->left=NULL;
     39         tree->right=NULL;
     40     }
     41     for (i=2;i<=n;i++)
     42     {
     43         scanf("%ld",&s);
     44         p=(struct node *) malloc (sizeof(struct node));
     45         p=tree;
     46         while (p)
     47         {
     48             if (s<p->d)
     49             {
     50                 if (p->left!=NULL)
     51                     p=p->left;
     52                 else
     53                 {
     54                     q=(struct node *) malloc (sizeof(struct node));
     55                     q->d=s;
     56                     q->left=NULL;
     57                     q->right=NULL;
     58                     p->left=q;
     59                     break;
     60                 }
     61             }
     62             else
     63             {
     64                 if (p->right!=NULL)
     65                     p=p->right;
     66                 else
     67                 {
     68                     q=(struct node *) malloc (sizeof(struct node));
     69                     q->d=s;
     70                     q->left=NULL;
     71                     q->right=NULL;
     72                     p->right=q;
     73                     break;
     74                 }
     75             }
     76         }
     77     }
     78     scanf("%ld",&m);
     79     for (i=1;i<=m;i++)
     80     {
     81         scanf("%ld",&s);
     82         if (n==0)
     83         {
     84             printf("%ld do not exist
    ",s);
     85             continue;
     86         }
     87         p=(struct node *) malloc (sizeof(struct node));
     88         p=tree;
     89         while (p)
     90         {
     91             if (p->d==s)
     92             {
     93                 printf("%ld exist
    ",s);
     94                 break;
     95             }
     96             else if (s<p->d)
     97             {
     98                 if (p->left!=NULL)
     99                     p=p->left;
    100                 else
    101                 {
    102                     printf("%ld do not exist
    ",s);
    103                     break;
    104                 }
    105             }
    106             else
    107             {
    108                 if (p->right!=NULL)
    109                     p=p->right;
    110                 else
    111                 {
    112                     printf("%ld do not exist
    ",s);
    113                     break;
    114                 }
    115             }
    116         }
    117     }
    118     //print tree
    119     //任意一个结点,左子结点(如果有)的值小于该结点的值,右子结点(如果有)的值大于该结点的值
    120     //所以采用中序遍历(LDR),对于任意一个结点,输出的先后顺序(不一定相邻)为左子结点,根结点,右子结点
    121     printf("Ascending Order: ");
    122     LDR(tree);
    123     return 0;
    124 }
    125 /*
    126 6
    127 2 6 1 3 3 4
    128 3
    129 1 4 7
    130 */

          

    优化:

    Size Balanced Tree(SBT)

    AVL树

    红黑树

    Treap(Tree+Heap)

    这些均可以使查找树的高度为O(log(n))。

     

     

     /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

     

    二叉排序树

    ——二叉排序树的值都不相同

    二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:

    1)若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;

    2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;

    3)左、右子树也分别为二叉排序树;

     

     

    二叉排序树的修改版(这篇文章中简称为二叉排序树):

    1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;

    2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;

    3)左、右子树也分别为二叉排序树的修改版;

     

           I.建树:

           初始时树为空。

    对于第一个数,直接作为树的根结点。

           对于堆中的一个数,起始时设置与之比较的结点为树的根结点,该数与结点的值比较,若该数与结点的值相等,则无操作,结束;若该数比结点的值小,则结点变为结点的左子结点;若该数比结点的值大,则结点变为结点的右子结点。直到结点为空,则增加一个结点,为之前结点的左/右子结点,并写入数值。

           II.判断是否出现:

           对于一个需要判断的数,起始时设置与之比较的结点为树的根结点,该数与结点的值比较,若该数与结点的值相等,则该数在堆中出现,结束比较;若该数比结点的值小,则结点变为结点的左子结点;若该数比结点的值大,则结点变为结点的右子结点。直到结点为空,则该数在堆中没有出现,结束比较。

     

     

           建树保证二叉排序树的值都不相同:

    1.不加任何数时,二叉排序树的值都不相同。

    2.假设某个数未加之前二叉排序树的值都不相同,加入数s后,

    对于某个数s在建树中经过的所有结点,都有:

    I.若从结点(值为t)到达结点的左子结点,则s<t<该结点的右子树的所有结点的数值,即与该结点的右子树的所有结点的数值都不相同。

    II.若从结点(值为t)到达结点的右子结点,则s>t>该结点的左子树的所有结点的数值,即与该结点的左子树的所有结点的数值都不相同。

    III.若该结点的数值(值为t)等于数s,则s=t>该结点的左子树的所有结点的数值,s=t<该结点的右子树的所有结点的数值。

    所以加入该数后,二叉排序树的值仍然都不相同。

    所以建树保证二叉排序树的值都不相同。

     

    例子:

     

    建树保证满足二叉排序树 “对于树中的任意一个结点,若该结点有左子结点,则左子结点的值小于等于该结点的值,若该结点有右子结点,则右子结点的值大于等于该结点的值” 的性质:

    新加入的数满足上述条件,而其它数没有变化,也满足上述条件。所以所有的点满足上述条件。

     

     

           建树和输出的时间复杂度都大约为树所有结点的高度之和。而当树满足线性结构时(内部结点的出度都为1),可用归纳假设证明树所有结点的高度之和最大。

    1.结点为0的树满足当满足线性结构时,树所有结点的高度之和最大;

    2.假设一棵结点数目为n的树,当满足线性结构时,树所有结点的高度之和最大。对于一棵结点数目为n的树增加一个结点,增加的结点高度最大为n,当树满足线性结构时成立。所以一棵结点数目为n+1的树,当满足线性结构时,树所有结点的高度之和最大。

    所以得证。

     

     

    建树+输出的最坏时间复杂度:

    把数按照从小到大或从大到小的顺序加入树中,每次新的结点是上次结点的左/右子结点。树的深度为树所有结点的高度之和,大约为n*n/2,即建树和输出的时间复杂度都为O(n*n/2),总的时间复杂度为O(n*n)。

     

    建树+输出的平均复杂度:O(nlogn)

     

    判断是否出现平均时间复杂度:O(logn),最坏时间复杂度:O(n)。

     

     Code:

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <malloc.h>
      4 
      5 //二叉排序树(判断一个数是否出现在一个序列中)
      6 //1.排序:相同的数要加进去
      7 //2.判断某些数是否在一个序列中
      8 //所以当序列加入二叉排序树中,相同的数不必加入
      9 //但是相同的数不必再加入:需要每次都判断两个数是否相同,时间消耗长,反不如让相同的数也加入树中(如果序列中的数基本不相同)
     10 
     11 struct node
     12 {
     13     long d;
     14     struct node *left;
     15     struct node *right;
     16 }*tree;
     17 
     18 void LDR(struct node *p)
     19 {
     20     if (p!=NULL)
     21     {
     22         LDR(p->left);
     23         printf("%ld ",p->d);
     24         LDR(p->right);
     25     }
     26 }
     27 
     28 int main()
     29 {
     30     struct node *p,*q;
     31     long n,m,s,i;
     32     scanf("%ld",&n);
     33     if (n>=1)
     34     {
     35         scanf("%ld",&s);
     36         tree=(struct node *) malloc (sizeof(struct node));
     37         tree->d=s;
     38         tree->left=NULL;
     39         tree->right=NULL;
     40     }
     41     for (i=2;i<=n;i++)
     42     {
     43         scanf("%ld",&s);
     44         p=(struct node *) malloc (sizeof(struct node));
     45         p=tree;
     46         while (p)
     47         {
     48             if (s<p->d)
     49             {
     50                 if (p->left!=NULL)
     51                     p=p->left;
     52                 else
     53                 {
     54                     q=(struct node *) malloc (sizeof(struct node));
     55                     q->d=s;
     56                     q->left=NULL;
     57                     q->right=NULL;
     58                     p->left=q;
     59                     break;
     60                 }
     61             }
     62             else
     63             {
     64                 if (p->right!=NULL)
     65                     p=p->right;
     66                 else
     67                 {
     68                     q=(struct node *) malloc (sizeof(struct node));
     69                     q->d=s;
     70                     q->left=NULL;
     71                     q->right=NULL;
     72                     p->right=q;
     73                     break;
     74                 }
     75             }
     76         }
     77     }
     78     scanf("%ld",&m);
     79     for (i=1;i<=m;i++)
     80     {
     81         scanf("%ld",&s);
     82         if (n==0)
     83         {
     84             printf("%ld do not exist
    ",s);
     85             continue;
     86         }
     87         p=(struct node *) malloc (sizeof(struct node));
     88         p=tree;
     89         while (p)
     90         {
     91             if (p->d==s)
     92             {
     93                 printf("%ld exist
    ",s);
     94                 break;
     95             }
     96             else if (s<p->d)
     97             {
     98                 if (p->left!=NULL)
     99                     p=p->left;
    100                 else
    101                 {
    102                     printf("%ld do not exist
    ",s);
    103                     break;
    104                 }
    105             }
    106             else
    107             {
    108                 if (p->right!=NULL)
    109                     p=p->right;
    110                 else
    111                 {
    112                     printf("%ld do not exist
    ",s);
    113                     break;
    114                 }
    115             }
    116         }
    117     }
    118     //print tree
    119     //任意一个结点,左子结点(如果有)的值小于该结点的值,右子结点(如果有)的值大于该结点的值
    120     //所以采用中序遍历(LDR),对于任意一个结点,输出的先后顺序(不一定相邻)为左子结点,根结点,右子结点
    121     printf("Ascending Order: ");
    122     LDR(tree);
    123     return 0;
    124 }
    125 /*
    126 6
    127 2 6 1 3 3 4
    128 3
    129 1 4 7
    130 */

     

          

    优化:

    Size Balanced Tree(SBT)

    AVL树

    红黑树

    Treap(Tree+Heap)

    这些均可以使查找树的高度为O(log(n))。

     

     

    /////////////////////////////////////////////////////////////////////////////////

    某种求法的错误性:

     

     

     

    当t->lson/rson为空时,call InsertNode()。然后t=nil,对t赋值为s,但之前的t->lson/rson仍为空。所以不能这样做,必须在t->lson/rson为空时,修改t->lson/rson的值。

  • 相关阅读:
    part7-1 Python 的异常处理(try...except 捕获异常、异常类继承、访问异常信息、else、finally回收资源、raise引发异常、自定义异常类、except 和 raise 同时使用)
    part6-3 Python 类和对象练习
    part6-2 Python 类和对象(类变量和实例变量区别、property 函数定义属性及装饰器方法、隐藏和封装、继承(方法重写、未绑定方法调用)、super函数使用、动态与__slots__、type()定义类、metaclass使用、多态、issubclass、isinstance、__bases__ 属性、__subclasses__()方法、枚举类)
    贪心 No Time for Dragons Gym
    Bellman-Ford变形 Currency Exchange POJ
    Heavy Transportation POJ
    最短路变形 Frogger POJ
    最短路 Til the Cows Come Home POJ
    Song Jiang's rank list UVALive
    简单BFS +打印路径 迷宫问题 POJ
  • 原文地址:https://www.cnblogs.com/cmyg/p/6911035.html
Copyright © 2011-2022 走看看