//检索树的构造、查找、插入、删除等综合程序
//其中,插入函数是非递归的
//检索树的构造、查找、插入、删除等综合程序
//其中,插入函数是非递归的
#include <stdio.h>
#include <ctype.h>
#include <malloc.h> //包含动态存储分配函数malloc和free等
#include <stdlib.h> //异常终止函数exit所在的库文件
#define M 100 //结点个数的最大值
#define ZERO 0 //定义空结点值
#define SUCC 1 //删除成功的返回值
#define DEFT 0 //定义删除失败的返回值
#define MIN -1 //定义无穷小元素值
#define MAX 2001 //定义无穷大元素值
typedef int valuetype; //假定值类型是int
typedef struct Bnode //定义二叉树结点类型Bnode
{ valuetype data; //值域
int layer; //结点的层号域layer
struct Bnode *Lson, *Rson; //指向左右儿子的链域
} Bnode, *Bptr; // 定义结点类型名和指针类型名
//按层输出二叉树的函数
void writeT(Bptr root)
{ int frist=0,last=1;
Bptr p,q[M];
if(root->data==MIN)p=root->Rson; else p=root->Lson;//p指向真根结点
if(p==NULL)
{ printf(" 当前二叉树为空,没有结点。\n"); return;}
printf(" 当前二叉树中的结点为:\n");
printf(" 层号 当前结点 左儿子 右儿子\n");
p->layer=1; //根结点的层号为1
q[0]=p;
while(frist!=last)
{ p=q[frist++]; //队头结点出队
printf("%6d%10d ",p->layer,p->data); //输出当前结点
if(p->Lson==NULL)printf("%12c",'\040'); //左儿子为空时,输出足够的空格
else //左儿子不空
{ printf("%12d",p->Lson->data); //输出左儿子
p->Lson->layer=p->layer+1; //给左儿子定层号
q[last++]=p->Lson; //左儿子进队
}
if(p->Rson!=NULL) //若右儿子不空
{ printf("%12d",p->Rson->data);//输出右儿子
p->Rson->layer=p->layer+1; //给右儿子定层号
q[last++]=p->Rson;//右儿子进队
}
printf("\n"); //每个结点占一行
}
}
//中序遍历函数
void inorder(Bptr p)
// p指向当前子树的根结点
{
if(!p) return; //若p等于NULL,什么也不做,返回
inorder(p->Lson);
printf("%5d",p->data);
inorder(p->Rson);
}
//排序输出树中结点的函数
void sortT(Bptr root)
{
if(root->data==MIN) inorder(root->Rson);
else inorder(root->Rson);
printf("\n");
}
//算法4-8 检索树的查找算法
Bptr search(valuetype x,Bptr p)
//参数x是待查元素值
//参数p是指向当前结点的指针
//返回值是指向值为x的结点指针;若x不在树中,返回NULL
{
while(p!=NULL)
{ if (x==p->data) return p; //找到x,返回指向结点x的指针
if (x<p->data) p=p->Lson; //转向左子树查找
else p=p->Rson; //转向右子树查找
}
return NULL; //遇到空树,表明没查到x,返回NULL
}
//主调语句:p=search(x,root);
//查找操作
void searchT(Bptr root)
//root是指向当前结点的指针
{ int x;
printf("请输入要查找的结点值x>0,x=");
scanf("%d",&x);
if(search(x,root) ==NULL) printf("树中没有 %d !\n",x);
else printf(" %d 已被找到!\n ",x);
}
//********************************
//算法4-9 检索树非递归的插入算法
//主调语句为: insert( x, root);
void insert(valuetype x, Bptr &root)
//x是待插入元素值
// root是指向根结点的指针
{ Bptr f,p;
f=NULL; p=root; //采用f和p双指针搜索法,f将指向p的父结点
while(p!=NULL) //一直查到p等于空
if(x<=p->data) f=p, p=p->Lson; //转向左子树
else f=p, p=p->Rson; //转向右子树
//程序执行到此处时,p的值等于NULL
p=(Bptr)malloc(sizeof(Bnode)); //产生新结点
p->data=x; p->Lson=p->Rson=NULL; //x做新叶
if(f==NULL) root=p; //若插入前树为空,则x做根
else
if(x<=f->data) f->Lson=p; // x做f的左儿子
else f->Rson=p; // x做f的右儿子
}
//插入操作
void insertT(Bptr p)
{ int x;
printf("请输入要插入的结点值x>0,x=");
scanf("%d",&x);
insert(x,p);
printf(" %d 已被插在树中。\n",x);
}
//算法4-12 检索树的构造算法
//主调语句:root=creatST( );
Bptr creatST( )
//输入以ZERO为结束标记的元素序列
//返回所构造的二叉树根结点指针
{ Bptr root; valuetype x;
root=NULL; //造一个空树
printf(" 构造初始检索树,请输入元素序列,元素个数不超过 %d,要求: \n",M);
printf("序列以 %d 或 %d 开始,以 0 结束,元素值均为小于 %d的正整数\n",MIN,MAX,MAX);
scanf("%d",&x); //读入元素x
while(x!=ZERO) //x不是结束标记ZERO时,循环
{ insert(x,root); //将x插到树中
scanf("%d",&x); //读入下一个x值
}
return root; //退出循环后,返回根指针
}
//&&&&&&&&&&&&&&&&&&&&&
//算法4-13 带表头监督元结点的检索树删除算法
//主调语句形如:k=deleteST(x,root);
int deleteST(valuetype x, Bptr root)
//root是根指针(指向监督元结点),x是要删除的结点值
{ Bptr f,p,s,r;
//句1至句5的循环用于查找x
for(p=root; ; ) //p是搜索指针,初值指向虚根
{
if(p==NULL) return DEFT; //遇到空树,x不在树中,返回删除不成功信息
if(x==p->data) break; //找到x后,退出循环
if(x<p->data) {f=p; p=p->Lson;} //向左
else { f=p; p=p->Rson;} //向右
}//循环体结束
//以下是找到x后(p指向x)的处理步骤
if (p->Rson==NULL)
// p没有右儿子(是叶,或只有左儿子),用左儿子代替p
{ if (p==f->Lson) f->Lson=p->Lson; else f->Rson=p->Lson;
free(p); //删去p
return SUCC; //返回删除成功信息
}
if (p->Lson==NULL)
// p有右儿子,无左儿子,用右儿子代替p
{ if (p==f->Lson) f->Lson=p->Rson; else f->Rson=p->Rson;
free(p); //删去p
return SUCC; //返回删除成功信息
}
//以下处理p有两个儿子的情况
s=p->Lson; //s是p的左儿子
if (s->Rson==NULL)
//p的左儿子s没有右儿子,s是p的中序前趋
{ p->data=s->data; //用s的值域代换p的值域
p->Lson=s->Lson;
free(s); //删去s
return SUCC; //返回删除成功信息
}
//p的左儿子s有右儿子
r=s->Rson; //找p的左儿子的最右子孙r
while(r->Rson!=NULL) {s=r; r=r->Rson;} //r始终是s的右儿子
p->data=r->data; //用r的值域代换p的值域
s->Rson=r->Lson;
free(r); //删去r
return SUCC; //返回删除成功信息
}//函数结束
//删除操作
void deleteT( Bptr root)
//root为根指针
{ int x;
printf("请输入要删除的结点值x>0,x=");
scanf("%d",&x);
if(deleteST(x,root))
printf(" %d 已被删除! \n",x);
else printf(" %d 不在树中,无法删除!\n",x);
}
char getalpha()
{ char c;
while(1)
{ c=getchar();
if(isalpha(c))return c;
}
}
void treeT(Bptr root)
{ char c;
printf(" 对检索树可以进行下列操作:\n");
printf("F/f:查找; I/i:插入\nD/d:删除; P/p:显示树中结点\n");
printf("S/s:结点排序; E/e:退出; 其他字母:程序继续! \n");
while(1)
{ printf("请输入操作码:查找F,插入I,删除D,显示P,结点排序S,终止E)?");
c=getalpha();
switch(c)
{
case 'f':
case 'F': searchT(root); break; //查找
case 'p':
case 'P': writeT(root); break; //显示
case 'i':
case 'I': insertT(root); break; //插入
case 'd':
case 'D': deleteT(root); break; //删除
case 's':
case 'S': sortT(root); break; //结点排序输出
case 'e':
case 'E': writeT(root); return; //退出
default : printf("输入操作码不对,请重新输入! \n");continue ; //继续
}
}
}
int main( ) //主函数
{ Bptr root;
root= creatST( );//构造初始检索树
treeT(root);
printf("程序结束,再见!\n");
}
检索树
最新推荐文章于 2022-11-13 20:14:31 发布