26、动态查找树之二叉排序数

一、二叉排序树概念

二叉排序树又称为二叉查找树。它或者是空树,或者是满足如下性质的二叉树:

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

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

(3)它的左、右子树本身又各是一棵二叉排序树。

二、二叉排序树算法思想

1、插入基本思想

若二叉排序树为空,将待插入的结点作为根结点。否则,若待插入结点的关键字值和根结点关键字值进行比较。若小于,则作为根结点左子树插入,否则作为右子树插入。

按中序遍历该二叉树所得到的序列是一个递增有序序列。二叉排序树是用非线性结构表示有序线性表的一种方法。

2、二叉排序树的查找基本思想

(1)当二叉树为空树时,检索失败。    

(2)如果二叉排序树根结点的关键字等于待检索的关键字,则检索成功。  

(3)如果二叉排序树根结点的关键字小于待检索的关键字,则在根结点的右子树中用相同的方法继续检索。    

(4)如果二叉排序树根结点的关键字大于待检索的关键字,则在根结点的左子树中用相同的方法继续检索。 

3、二叉排序树的删除基本思想

(1)若待删除的结点是叶结点,直接删去该结点。

(2)若待删除的结点只有左子树而无右子树。根据二叉排序树的特点,可以直接将其左子树的根结点放在被删结点的位置。

(3)若待删除的结点只有右子树而无左子树。与(2)情况类似,可以直接将其右子树的根结点放在被删结点的位置。

(4)若待删除的结点同时有左子树和右子树。根据二叉排序树的特点,可以从其左子树中选择关键字最大的结点(直接前驱结点)或右子树中选择关键字最小的结点(直接后继结点)放在(覆盖)被删去结点的位置上。假如选取右子树上关键字最小的结点,那么该结点一定是右子树的最左结点。假如选取左子树上关键字最大的结点,那么该结点一定是左子树的最右结点。

三、二叉排序数的操作及C语言描述

1、插入

2、查找

3、删除

四、二叉排序数的C语言实现

#include"stdio.h"

#include"stdlib.h"

#include"string.h"

#include"math.h"

#define OK 1

typedef intKeyType;

typedef int info;

typedef struct 

{

KeyType key;

//info otherinfo;

}ElemType;

typedef structBiTNode

 {

   ElemType data;

   BiTNode *lchild,*rchild; // 左右孩子指针

 }BiTNode,*BiTree;

intSearchBST(BiTree T,KeyType key,BiTree f,BiTree &p)

{

if(!T) {p=f;return0;}

elseif(key==T->data.key) {p=T;return 1;}

elseif(key<T->data.key) SearchBST(T->lchild,key,T,p);

else  SearchBST(T->rchild,key,T,p);

}//SearchBST

intInsertBST(BiTree &T,ElemType e)

{

BiTree s,p;    

if(!SearchBST(T,e.key,NULL,p))

   {

    s=(BiTree)malloc(sizeof(BiTNode));

       s->data=e;

       s->lchild=s->rchild=NULL;

       if(!p) T=s;

       else if(e.key<p->data.key)p->lchild=s;

       else p->rchild=s;

       return 1;

   }

else return 0;

}//InsertBST

int Delete(BiTree&p)

{

BiTree q,s;    

if(!p->rchild)

  {

   q=p;

   p=p->lchild;

   free(q);

  }//if

elseif(!p->lchild)

  {

   q=p;

   p=p->rchild;

   free(q);

  }//else if

else 

   {

    q=p;

       s=p->lchild;

       while(s->rchild) {q=s;s=s->rchild;}

       p->data=s->data;

       if(q!=p) q->rchild=s->lchild;

       else q->lchild=s->lchild;

       delete s;

   }//else

return 1;

}//Delete 

intDeleteBST(BiTree &T,KeyType key)

{

if(!T) return 0;

else

  {

   if(key==T->data.key) return Delete(T);

   else if(key<T->data.key) returnDeleteBST(T->lchild,key);

   else return DeleteBST(T->rchild,key);

  }//else

}//DeleteBST

intInsertBSTD(BiTree &T)

{

ElemType e; 

printf("insertthe data,until input -1:\n");      

scanf("%d",&e.key);

while(e.key!=-1)

       {

       InsertBST(T,e);

       scanf("%d",&e.key);

    }//while

return 1;

}//InsertBSTD

void PrintD(BiTreeT)

{

if(T->lchild)PrintD(T->lchild);

printf("->%d",T->data.key);

if(T->rchild)PrintD(T->rchild);

}//PrintD

intDeleteBSTD(BiTree &T)

{

ElemType e;        

printf("\ninputthe data you want to delete:\n");

scanf("%d",&e.key);

DeleteBST(T,e.key);

return 1;

}//DeleteBSTD

int main()

 {

       BiTree T;

       InsertBSTD(T);

       PrintD(T);

       DeleteBSTD(T);

       PrintD(T);

       return OK;

 }

五、复杂度分析

在二叉排序树上查找其关键字等于给定值的结点的过程,恰是走了一条从根结点到该结点的路径的过程。和给定值比较的关键字次数等于路径长度加1(或结点所在层次数)。因而,和折半查找类似,与给定值比较的关键字个数不超过树的深度。然而,折半查找长度为n的表的判定树是惟一的,而含有n个结点的二叉排序树并不唯一,其平均查找长度和树的形态有关。如图所示:

其同样的数据,输入的顺序不同,其树的形态就不一样,导致平均查找长度也不一样。当表中记录按关键字有序时,构成的二叉排序树蜕变为歪斜树。树的深度为n,其平均查找长度为(n+1)/2(和顺序查找相同),这是最差的情况。显然,最好情况下平均查找长度和log2n成正比。那么平均性能如何呢?在随机输入数据的情况下,其平均查找长度是多少呢?

可见,在随机的情况下,二叉排序树的平均查找长度和logn是等数量级的。

为了避免出现歪斜树,在构造二叉排序树的过程中需要不断进行平衡处理,使其成为平衡二叉树。  

 

 

 

发布了278 篇原创文章 · 获赞 31 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/hopegrace/article/details/104495450
今日推荐