7-1 还原二叉树 (25 分)

7-1 还原二叉树 (25 分)

给定一棵二叉树的先序遍历序列和中序遍历序列,要求计算该二叉树的高度。
输入格式:

输入首先给出正整数N(≤50),为树中结点总数。下面两行先后给出先序和中序遍历序列,均是长度为N的不包含重复英文字母(区别大小写)的字符串。
输出格式:

输出为一个整数,即该二叉树的高度。
输入样例:

9
ABDFGHIEC
FDHGIBEAC

输出样例:

5

最简便的方法
#include <stdio.h>
#include <stdlib.h>

char x[50],z[50];//由于是全局变量,不用在形参了,看以直接调用
typedef struct TreeNode *Tree;
struct TreeNode
{
char data;
Tree right,left;
};

Tree RestoreTree(int x1,int x2,int z1,int z2)
{
Tree head =(Tree)malloc(sizeof(struct TreeNode));
head -> data = x[x1];//并不能写成head->data=x[0],因为并不是每次根都为0
head->left =head->right =NULL;
for(int i = z1;i <= z2;i ++)//重点<=z2
{
if(z[i] == x[x1])
{//因为已经有了总的根节点//x1+i-z1=从中序等左子树的长度,(i-1)-z1,字后在前序取左子树的长度(x1+1)+[(i-1)-z1]
if(i != z1)head -> left = RestoreTree(x1 + 1,x1+i-z1,z1,i - 1);
if(i != z2)head -> right = RestoreTree(x1 + i - z1 + 1,x2,i + 1,z2);//柚子社前序的开始地址为,左子树结束地址+1
break;
}
}
return head;
}
int max(int a,int b)
{
if(a>b)return a;
return b;
}
int Theight(Tree tree)
{
if(tree == NULL)return 0;
return max(Theight(tree -> left),Theight(tree -> right))+1;
}
int main()
{
int n;
scanf("%d",&n);
scanf("%s%s",x,z);
Tree head = RestoreTree(0,n-1,0,n-1);
printf("%d",Theight(head));
}

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct TNode *position;
struct TNode{
char Data;
position Left;
position Right;
};
typedef position Tree;
Tree restoreTree(char pre[],char in[],int n)
{
int i,j;
Tree T;
int n1=0,n2=0;
int m1=0,m2=0;
char lin[100],rin[100];//中旭的左右
char lpre[100],rpre[100];//前序左右
if(n==0)
{
return NULL;
}

	T=(Tree)malloc(sizeof(struct TNode));//不要忘了
//	T->Left =T->Right =NULL;
	 T->Data =pre[0];
	for(i=0;i<n;i++)//中序遍历,找到左右树 
	{
		if(i<=n1&&in[i]!=T->Data ){//找到左
			lin[n1++]=in[i];
			}
			else if(in[i]!=pre[0])
			{//找到右 
				rin[n2++]=in[i];
			}
		
	}
	for(i=1;i<n;i++)//处理前序,找到前序的左子树,右树 
	//(目的是,下一次递归时,有前序的左,右 指数的第一个值,为根节点 
	{
		if(i<(n1+1))
		{
			lpre[m1++]=pre[i];
		 } 
		 else {
		 	rpre[m2++]=pre[i];
		 }
	 } 
	 //,(再将其左子树在分,根节点,左孩子,右孩子)传入的是前序的左子树,中序的左子树,左子树的长度
	 T->Left =restoreTree(lpre,lin,n1);
	
	 T->Right = restoreTree(rpre,rin,n2);
	 //,(再将其右子树在分,根节点,左孩子,右孩子)传入的是前序的右子树,中序的右子树,右子树的长度
return T;

}
int getheight(Tree BST)
{
int hr=0,hL=0,hmax=0;
if(BST==NULL)
{
return 0;
}
else
{
hL=getheight(BST->Left );
hr=getheight(BST->Right );
hmax=hL>hr? hL:hr;
return hmax+1;
}
}
int main()
{
int n,i;
char pre[100],in[100];
scanf("%d",&n);
scanf("%s",pre);
scanf("%s",in);
Tree BST;
BST=restoreTree(pre,in,n);

int h=getheight(BST);
printf("%d",h);
return 0;

}
/*
这个备注更详细些
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct TNode *position;
struct TNode{
int Data;
position Left;
position Right;
};//二叉树的结构体
typedef position Tree;
Tree restoreTree(char pre[],char in[],int n){//还原二叉树的函数
int i;
char lpre[60],rpre[60];
char lin[60],rin[60];
int n1 = 0,n2 = 0;//n1记录前序遍历序列的左子树长度n2则记录前序遍历序列的右子树长度
int m1 = 0,m2 = 0;//m1记录中序遍历序列的左子树长度m2记录中序遍历序列右子树长度
if(n==0){//如果长度为零说明这可子树建完了返回NULL
return NULL;
}
Tree T = (Tree)malloc(sizeof(struct TNode));

T->Data = pre[0];//每一次,一定是前序遍历的第一个作为根节点,然后再去建左右子树
//下面是关键,通过根节点把中序遍历分出左右子树,然后再根据这个分好的长度,再把前序遍历分成相同长度,依次确定根节点,递归实现

//分中序遍历序列 
for(i = 0; i < n; i++){
	if(i<=n1&&in[i]!=pre[0]){//中序遍历被根节点分开的左子树的点 
		lin[n1++] = in[i];
		
	}
	else if(in[i]!=pre[0]){//右子树的点,注意是else if,因为这个时候i是大于n1的 
		rin[n2++] = in[i];
	
	}
}
//分前序遍历序列,注意!这里从1开始循环,因为0号元素作为根 
for(i = 1; i < n; i++){
	if(i<(n1+1)){
		lpre[m1++] = pre[i];
		
	}
	else{
		rpre[m2++] = pre[i];
	
	}
}
T->Left = restoreTree(lpre,lin,n1);
T->Right = restoreTree(rpre,rin,n2);
return T;//最后一定要return这颗树,要不然怎么算高。。。 

}
int getHight(Tree BST){//得到树的高度,已知左右树高,树高为max(左树高,右树高)+1;
int lh,rh;
if(BST==NULL){
return 0;
}
else {
lh = getHight(BST->Left);
rh = getHight(BST->Right);
return (lh>rh?lh:rh)+1;
}

}
int main(){
char pre[60],in[60];
int n;

scanf("%d",&n);
scanf("%s",pre);
scanf("%s",in);//输入 
Tree BST = NULL;
BST = restoreTree(pre,in,n);//建树 
int hight;
hight = getHight(BST);//求高 
printf("%d\n",hight);//输出 
return 0;

}

*/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值