题目描述
1、给定一棵二叉树的先序和中序序列,以单个字母表示一个节点,用一个字符串表示的一种序列,构造该二叉树。
2、采用后序遍历,输出后序遍历结果。
3、输入与输出字符之间没有空格或其它字符。
相关数据结构的一些简单算法
先序遍历
void PreOrderTraverse(BiTree T){
if(T==NULL){
return;
}
printf("%c",T->data);
PostOrderTraverse(T->lchild);//先遍历左子树
PostOrderTraverse(T->rchild);//在遍历右子树
中序遍历
void InOrderTraverse(BiTree T){
if(T==NULL){
return;
}
PostOrderTraverse(T->rchild);//在遍历右子树
PostOrderTraverse(T->lchild);//先遍历左子树
printf("%c",T->data);
后序遍历
void PostOrderTraverse(BiTree T){
if(T==NULL){
return;
}
PostOrderTraverse(T->lchild);//先遍历左子树
PostOrderTraverse(T->rchild);//在遍历右子树
printf("%c",T->data);
}
相关的遍历在代码上只是顺序不同
我一般这样记:先序:根左右,中序左根右,后序:左右根
本题思路分析
我们已经知道先序遍历和中序遍历,我们便可以唯一确定一颗二叉树,并可以还原该二叉树,并通过上文提及的递归公式获得后序遍历,我们关键是需要还原二叉树
BiTree 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)
{
return NULL;
}
BiTree T = (BiTree)malloc(sizeof(struct BiTNode));//创立节点
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)) // 这里n1+1是因为编号是从1开始的,共有n1个左子树
{
lpre[m1++] = pre[i];
}
else
{
rpre[m2++] = pre[i]; // 其余为右子树
}
}
T->lchild = restoreTree(lpre, lin, n1);
T->rchild = restoreTree(rpre, rin, n2);
//通过若干次递归最后实现二叉树的还原
return T;
}
完整代码
```c
#include<stdio.h>
#include "stdlib.h"
#include "string.h"
//二叉树的二叉链表结构
typedef struct BiTNode{
char data;
struct BiTNode *lchild,*rchild;//左右孩子指针
}BiTNode,*BiTree;
char pre_string[30];
char in_string[30];
BiTree restoreTree(char pre[], char in[], int n)
{
int i;
char lpre[60],rpre[60];
char lin[60],rin[60];
int n1,n2;
n1=n2=0;
int m1=0,m2=0;
if(n==0){
return NULL;
}
BiTree T=(BiTree)malloc(sizeof(struct BiTNode));
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]){
rin[n2++]=in[i];
}
}
for(i=1;i<n;i++){
if(i<n1+1){
lpre[m1++]=pre[i];
}
else{
rpre[m2++]=pre[i];
}
}
T->lchild=restoreTree(lpre,lin,n1);
T->rchild=restoreTree(rpre,rin,n2);
return T;
}
//后续遍历
void PostOrderTraverse(BiTree T){
if(T==NULL){
return;
}
PostOrderTraverse(T->lchild);//先遍历左子树
PostOrderTraverse(T->rchild);//在遍历右子树
printf("%c",T->data);
}
int main(){
BiTree T;
T=NULL;
printf("please input The result of the traversal in order:");
gets(pre_string);
printf("please input The result of the traversal in preorder:");
gets(in_string);
int n=strlen(in_string);
T=restoreTree(pre_string,in_string,n);
PostOrderTraverse(T);
}