您的位置:首页 > 其它

二叉排序树

2015-10-06 20:55 846 查看
  以二叉树或树作为表的组织形式,称为树表。树表在进行插入或删除操作时,可以方便地维护表的有序性,不需要移动表中记录,从而减少因移动记录引起的额外时间开销。常见的树表有二叉排序树、平衡二叉树、B-数和B+数等。

  二叉排序树(简称BST)的定义为:二叉排序树或者是空树,或者满足以下性质的二叉树:

  (a) 若它的左子树非空,则左子树上所有记录的值均小于根记录的值;

  (b) 若它的右子树非空,则右子树上所有记录的值均大于根记录的值;

  (c) 左右子树本身又各是一颗二叉排序树。

  二叉排序树的特点是:左小右大根居中,因此中序遍历一颗二叉排序树时,得到的是一个递增有序序列。

  二叉排序树通常采用二叉链存储结构进行存储,其结点的类型定义如下:  

#define MaxSize 100
typedef int KeyType;
typedef char InfoType;
typedef struct node{
KeyType key;         //关键字项
InfoType data;       //其他数据域
struct node *lchild,*rchild; //左右孩子指针
}BSTNode;


  下面的代码演示建立二叉排序树、删除结点、查找某个值。

#include <stdio.h>
#include <malloc.h>
#define MaxSize 100 typedef int KeyType; typedef char InfoType; typedef struct node{ KeyType key; //关键字项 InfoType data; //其他数据域 struct node *lchild,*rchild; //左右孩子指针 }BSTNode;
int path[MaxSize];
void DispBST(BSTNode *b);

//在BSTree中插入一个结点k
int InsertBST(BSTNode *&p,KeyType k){
if (p==NULL)
{
p=(BSTNode *)malloc(sizeof(BSTNode));
p->key=k; p->lchild=p->rchild=NULL;
return 1;
}
else if(k==p->key) //若相等,则不插入
return 0;
else if(k < p->key)
return InsertBST(p->lchild,k); //插入到p的左子树中
else
return InsertBST(p->rchild,k); //插入到p的右子树中
}

//由数组A中的关键字建立一棵二叉排序树
BSTNode *CreatBST(KeyType A[],int n){
BSTNode *bt=NULL; //初始时bt为空树
int i=0;
while (i<n)
{
if (InsertBST(bt,A[i])==1) //将A[i]插入到二叉排序树T中
{
printf(" 第%d步,插入%d:",i+1,A[i]);
DispBST(bt); printf("\n");
i++;
}
}
return bt; //返回二叉排序树的根指针bt
}

//当被删*p结点有左右子树时的删除过程
void Delete1(BSTNode *p,BSTNode *&r){
BSTNode *q;
if(r->rchild!=NULL)
Delete1(p,r->rchild); //递归地找最右下结点
else{ //找到了最右下结点*r
p->key=r->key; //将*r的关键字值赋给*p
q=r;
r=r->rchild; //将*r的双亲结点的右孩子改为*r的左孩子结点
free(q); //释放原*r的空间
}

}

//从二叉排序树中删除*p结点
void Delete(BSTNode *&p){
BSTNode *q;
if (p->rchild==NULL) //当*结点没有右子树时
{
q=p; p=p->lchild; free(q);
}
else if (p->lchild==NULL) //当*p没有左子树时
{
q=p; p=p->lchild; free(q);
}
else Delete1(p,p->lchild); //当*p结点既有左子树,又有右子树时
}

//在bt中删除关键字为k的结点
int DeleteBST(BSTNode *&bt,KeyType k){
if(bt==NULL) return 0;
else{
if(k < bt->key)
return DeleteBST(bt->lchild,k);
else if( k > bt->key)
return DeleteBST(bt->rchild,k);
else{
Delete(bt);
return 1;
}
}
}

//以非递归方式输出从根结点到查找到的结点的路径
void SearchBST1(BSTNode *bt,KeyType k,KeyType path[],int i){
int j;
if(bt==NULL)
return;
else if (k==bt->key)
{
path[i+1]=bt->key;
for(j=0;j<=i+1;j++)
printf("%3d",path[j]);
printf("\n");
}
else{
path[i+1]=bt->key;
if(k < bt->key)
SearchBST1(bt->lchild,k,path,i+1);
else
SearchBST1(bt->rchild,k,path,i+1);
}

}

//以递归方式输出从根结点到查找到的结点的路径
int SearchBST2(BSTNode *bt,KeyType k){
if(bt==NULL)
return 0;
else if(k==bt->key)
{
printf("%3d",bt->key);
return 1;
}
else if(k < bt->key)
SearchBST2(bt->lchild,k);
else
SearchBST2(bt->rchild,k);
printf("%3d",bt->key);

}

//以括号表示法输出二叉排序树bt
void DispBST(BSTNode *bt){
if (bt!=NULL)
{
printf("%3d",bt->key);
if (bt->lchild!=NULL || bt->rchild!=NULL)
{
printf("(");
DispBST(bt->lchild);
if(bt->rchild!=NULL) printf(",");
DispBST(bt->rchild);
printf(")");
}
}

}

KeyType predt=-32627; //predt为全局变量,保存当前结点中序前趋的值,初值为-∞
int JudgeBST(BSTNode *bt){ //判断bt是否为BST
int b1,b2;
if(bt==NULL)
return 1;
else{
b1=JudgeBST(bt->lchild);
if(b1==0 || predt >= bt->key)
return 0;
predt=bt->key;
b2=JudgeBST(bt->rchild);
return b2;
}

}

void main()
{
BSTNode *bt;
KeyType k=6;
int a[]={4,9,0,1,8,6,3,5,2,7},n=10;
printf(" 创建一棵BST树:");
printf("\n");
bt=CreatBST(a,n);
printf(" BST:");DispBST(bt);printf("\n");
printf(" bt%s\n",(JudgeBST(bt)?"是一棵BST":"不是一棵BST"));
printf("\n");
printf(" 查找%d关键字(递归):",k);SearchBST1(bt,k,path,-1);
printf(" 查找%d关键字(非递归):",k);SearchBST2(bt,k);
printf("\n 删除操作:\n");
printf(" 原BST:");DispBST(bt);printf("\n");
printf(" 删除结点4:");
DeleteBST(bt,4);
DispBST(bt);printf("\n");
printf(" 删除结点5:");
DeleteBST(bt,5);
DispBST(bt);
printf("\n\n");
}


效果如下:


图(1) 用括号表示法,输出二叉排序树
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息