西北工业大学NOJ数据结构—018建立二叉树的二叉链表(以先序和中序为线索)

如果只给出一个先序或者中序或者后序序列,是可以构建多棵树的,但是若给出中序和前序或者给出中序和后序,则一定可以构建唯一的二叉树,因为中序数列最前的节点一定是根节点,然后再前序数列中按照根节点可以将序列分为两部分,左侧为左子树,右侧为右子树,通过递归调用可以依次构建二叉树。

不过若是给出前序和后序,则不一定可以构建唯一二叉树,因为根节点位置同样是不确定的。

解题思路:

1.构建一个递归函数,来构建二叉树,这个函数应该有以下特性:

1)每次调用都应该从前序数列中得到一个字符作为当前的根节点,并先把此节点的左右子树初始化为NULL

2)然后从中序数列中找到之前的到的字符的位置i

3)以中序数列中i左边的序列作为次级中序序列来递归构建左子树

4)以中序数列中i右边的序列作为次级中序序列来递归构建右子树

5)递归的3和4应该在i左侧或右侧没有字符时停止,即找到一个左右相碰的位置(挺复杂的函数对吧,,,,,)

(在纸上写了一下才找到确切的位置)

2.剩下的就是后序输出

3.为了实现1的函数,需要另外写以一个函数,一个用来在中序序列中找到某个字符的位置,并返回这个位置;

ok了万事大吉搞代码(づ ̄3 ̄)づ╭❤~

#include<stdio.h>  
#include<stdlib.h> 
#include<string.h> 

struct BinTree  
{  //定义二叉链表来储存二叉树
    char data;  
    struct BinTree *left;  
    struct BinTree *right;  
}; 

char pre[100];
char mid[100];//定义两个字符串来储存前序和中序

int lentgh(char *t)//得到一个字符串的长度
{
	int i=0;
	while(1)
	{
		if(!t[i])
			break;
		i++;
	}
	return i;
}

int find(int l,int r,char mi)//输入一个元素和查找范围,在中序序列中找到这个元素
{//并返回这个元素在中序列中的位置i
	int i;
	for(i=l;i<=r;i++)
	{
		if(mid[i]==mi)
			return (i);
	}
	return 0;
}

struct BinTree *creat(int l,int r,int *i)//创建二叉树,选择输入范围和在前序数列中的位置
{
	struct BinTree *cur;//abdfgceh和bfdgaceh序列
	cur=(struct BinTree*)malloc(sizeof(struct BinTree));
	cur->data=pre[*i];//根节点就是前序数列的元素
	cur->left=NULL;
	cur->right=NULL;
	(*i)++;
	int midnumber;
	midnumber=find(l,r,cur->data);//在中序中找到这个元素所在的位置
	if(midnumber>l)//如果这个位置比左极限大,就生成这个节点的左子树,直到相等就不创建了
		cur->left=creat(l,midnumber-1,i);//生成左子树,查找范围变为从左极限到中序数列位置减一
	if(midnumber<r)
		cur->right=creat(midnumber+1,r,i);//生成右子树,查找范围变为从中序数列位置加一到右极限
	return cur; 
}

void PostOrd(struct BinTree *T)
{//后序输出二叉树
	if(T->left)
		PostOrd(T->left);
	if(T->right)
		PostOrd(T->right);
	printf("%c",T->data);
}

int main()
{	
	memset(pre,0,sizeof(pre));
	memset(mid,0,sizeof(mid));//清零
	gets(pre);
	gets(mid);//依此输入前序和中序列
	int l=0,r=0;
	int len=lentgh(pre);//得到长度
	r=len-1;//最右位置为长度减一
	int i=0;
	struct BinTree *T;
	T=creat(l,r,&i);//创建二叉树
	PostOrd(T);//后序输出
	return 0;
}

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值