#include <stdio.h>
#include <malloc.h> //包含动态存储分配函数malloc和free等
#include <stdlib.h> //异常终止函数exit所在的库文件
#define Nuvalue 0
#define M 30
typedef int valuetype; //假定值类型是int
typedef struct Bnode //定义二叉树结点类型Bnode
{ valuetype data; //值域
struct Bnode *Lson, *Rson; //指向左右儿子的链域
int layer,height,sonnum;
} Bnode, *Bptr; // 定义结点类型名,和指向结点的指针类型名
int x;
//算法4-6 用中序序列和先序序列构造二叉树的函数
//主调语句:root=creat(a,b,0,n-1,0,n-1);
Bptr creat(int a[ ],int b[ ],int i,int j,int s,int t)
//数组a[n]和b[n]分别存储二叉树的先序序列和中序序列
//假定结点值全不同
//i和j是子二叉树的先序序列的一对下标界
//s和t是子二叉树的中序序列的一对下标界
//返回值是所构造的子树根结点指针值
{ int k; Bptr p;
if (i>j) return NULL; //序列为空时,返回一个空指针值
p=(Bptr)malloc(sizeof(Bnode));
p->data=a[i]; //造根结点
k=s;
while ((k<=t)&&(b[k]!=a[i])) k++; //在中序序列中找根
if(b[k]!=a[i])
{ printf("ERROR!\n"); //没找到根结点,出错
exit(1); //立即终止运行
}
p->Lson=creat(a,b,i+1,i+k-s,s,k-1); //递归地构造左子树
p->Rson=creat(a,b,i+k-s+1,j,k+1,t); //递归地构造右子树
return p; //返回根结点指针
}
//算法4-4 用先序遍历方法计算结点层数
//主调语句: level(root,1);
void level(Bptr p,int i)
// p指向当前子树的根结点
// i是当前子树根结点的层数
{
if(!p) return; //若p等于NULL,什么也不做,返回
p->layer=i; //填写层数域
level(p->Lson,i+1);
level(p->Rson,i+1);
}
//算法4-5 用后序遍历求二叉树各结点高度
//主调语句:h=high(root);
int high(Bptr p)
// p指向当前子树的根结点
{ int i,j;
if(!p) return 0; //空树的高度等于0
i=high(p->Lson); //递归地求左儿子高度
j=high(p->Rson); //递归地求右儿子高度
p->height=(i>j)? i+1: j+1; //求出结点高度
return (p->height); //返回所求高度,以便求父结点高度。
}
// 计算真子孙数量
int soncnt(Bptr p)
// p指向当前子树的根结点
{ int i,j=0;
if(!p) return 0; //空树的高度等于0
i=soncnt(p->Lson); //递归地求左儿子子孙数
j=soncnt(p->Rson); //递归地求右儿子子孙数
if(!p->Lson && !p->Rson) {
p->sonnum=0;
return 1;
}
p->sonnum = i+j;
return i+j+1;
}
//输出结点值的函数
void visit(Bptr p)
{printf("%4d",p->data);
}
//算法4-1 二叉树的先序遍历
//主调语句:preorder(root);
void preorder(Bptr p)
// p指向当前子树的根结点
{
if(p==NULL) return; //遇到空树,什么也不做
visit(p); //访问"根"结点
preorder(p->Lson); //递归地遍历左子树
preorder(p->Rson); //递归地遍历右子树
}
//算法4-2 二叉树的中序遍历
//主调语句:inorder(root);
void inorder(Bptr p)
// p指向当前子树的根结点
{
if(p==NULL) return; //遇到空树,什么也不做
inorder(p->Lson); //递归地遍历左子树
visit(p); //访问"根"结点
inorder(p->Rson); //递归地遍历右子树
}
//算法4-3 二叉树的后序遍历
//主调语句:postorder(root);
void postorder(Bptr p)
// p指向当前子树的根结点
{
if(p==NULL) return; //遇到空树,什么也不做
postorder(p->Lson); //递归地遍历左子树
postorder(p->Rson); //递归地遍历右子树
visit(p); //访问"根"结点
}
//按先序次序输出结点的层号、高度等
//主调语句:prewrite(root);
void prewrite(Bptr p)
// p指向当前子树的根结点
{
if(p==NULL) return; //遇到空树,什么也不做
printf("%6d%10d%10d ",p->data,p->layer,p->height);
if(p->Lson!=NULL) printf("%6d",p->Lson->data);
else printf("%6c",'\040');
if(p->Rson!=NULL) printf("%6d",p->Rson->data);
else printf("%6c",'\040');
printf("%10d",p->sonnum);
printf("\n");
prewrite(p->Lson); //递归地遍历左子树
prewrite(p->Rson); //递归地遍历右子树
}
//二叉树输出函数
void outtree(Bptr root)
{ printf(" 先序序列:\n");
preorder(root);
printf("\n");
printf(" 中序序列:\n");
inorder(root);
printf("\n");
printf(" 后序序列:\n");
postorder(root);
printf("\n");
printf(" 所构造的二叉树中的结点:\n");
printf(" 当前结点 层号 高度 左儿子 右儿子 真子孙\n");
prewrite(root);
}
void main( ) //主函数
{ Bptr root;
int c,h,n,i,a[M],b[M];
while(1)
{
printf("请选择操作码:\n");
printf(" 0:结束,1:构造二叉树:c=");
scanf("%d",&c);
if(!c) break;
if(c==1)
{ printf("请输入结点个数, n= ");
scanf("%d",&n);
printf("请输入先序序列!\n");
for(i=0;i<n;i++)scanf("%d",&a[i]);
printf("请输入中序序列!\n");
for(i=0;i<n;i++)scanf("%d",&b[i]);
root=creat(a,b,0,n-1,0,n-1);
level(root,1);
soncnt(root);
high(root);
outtree(root);
}
else
printf("操作码不对,请重新输入操作码!\n");
}
printf("程序结束,再见!\n");
}
介绍
根据给定的先序遍历和中序遍历,输出:
后序遍历
每个节点所处层数,左右子节点,真子孙数量