标签:i+1 因此 \n 中序遍历 class break 构建 str 简化
??利用后序和中序遍历可以将二叉树还原出来,以便于进行其他树的操作。在这里我们还原出二叉树之后进行先序遍历来求得先序遍历的结果,我们约定还原树的函数叫做RestoreTree()。
后序遍历实例:C B E H G I F D A
中序遍历实例:B C A E D G H F I
中序遍历开始位置,结束位置记做z1,z2,后序的记为h1,h2
??在恢复左右子树的时候,其位置需要算出来,即h1,h2和z1,z2的值需要重新计算,并在更新之后传递给RestoreTree()函数。以构建左子树为例,左子树的首元素下标为z1,最后一个元素下标为i-1,对应的h1的值为h1,h2的值为h1+(i-z1-1),也就是h1当前的位置向前移动i-z1-1个长度。
以实现之前提到的字母序列为例
#include<stdio.h>
#include<stdlib.h>
typedef struct Bitree{
char data;
struct Bitree* lchild;
struct Bitree* rchild;
}*bitree,bitnode;
bitree Createtree(void);
bitree Restoretree(int h1,int h2,int z1,int z2);
void Preorder(bitree bt);
char in[50],post[50];
int main(void)
{
int n;
scanf("%d",&n);
getchar();
//getchar()用于清除回车
for(int i = 0;i < n;i++)
scanf("%c",&post[i]);
getchar();
for(int i = 0;i < n;i++)
scanf("%c",&in[i]);
bitree b = Restoretree(0,n-1,0,n-1);
Preorder(b);
printf("\n");
return 0;
}
bitree Createtree(void)
{
bitree bt = (bitree)malloc(sizeof(bitnode));
bt->lchild = bt->rchild = NULL;
return bt;
}
bitree Restoretree(int h1,int h2,int z1,int z2)
{
bitree bt = Createtree();
bt->data = post[h2];
for(int i = z1;i <= z2;i++)
{
if(in[i]==post[h2])
{
if(i!=z1)//存在左子树,构建左子树
bt->lchild = Restoretree(h1,h1+i-z1-1,z1,i-1);
if(i!=z2)//存在右子树,构建右子树
bt->rchild = Restoretree(h2-z2+i,h2-1,i+1,z2);
break;//找到以后跳出遍历
}
}
return bt;
}
void Preorder(bitree bt)
{
if(!bt)
return;
printf("%c ",bt->data);
Preorder(bt->lchild);
Preorder(bt->rchild);
}
??由于代码在恢复树的时候先恢复的根结点,然后访问的左右子树,因此,恢复的过程也相当于一个先根遍历的过程.如果只想求先根遍历,可以不建树.我们可以删掉先根遍历的函数,同时简化一些其他的语句.修改后的代码如下:
#include<stdio.h>
typedef struct Bitree{
char data;
struct Bitree* lchild;
struct Bitree* rchild;
}*bitree,bitnode;
void Restoretree(int h1,int h2,int z1,int z2);
char in[50],post[50];
int main(void)
{
int n;
scanf("%d",&n);
getchar();
for(int i = 0;i < n;i++)
scanf("%c",&post[i]);
getchar();
for(int i = 0;i < n;i++)
scanf("%c",&in[i]);
Restoretree(0,n-1,0,n-1);
printf("\n");
return 0;
}
void Restoretree(int h1,int h2,int z1,int z2)
{
printf("%c ",post[h2]);
for(int i = z1;i <= z2;i++)
{
if(in[i]==post[h2])
{
if(i!=z1)//存在左子树,访问左子树
Restoretree(h1,h1+i-z1-1,z1,i-1);
if(i!=z2)//存在右子树,访问右子树
Restoretree(h2-z2+i,h2-1,i+1,z2);
break;//找到以后跳出遍历
}
}
}
两段代码得到的结果是一样的,以下是样例输入:
9
CBEHGIFDA
BCAEDGHFI
以下是输出:
A B C D E F G H I
??在这里补充一段利用先序遍历和中序遍历来还原二叉树并进行后序遍历的代码。
#include<stdio.h>
#include<stdlib.h>
typedef struct BiTree{
int data;
struct BiTree* lchild;
struct BiTree* rchild;
}bitnode,*bitree;
void Postorder(bitree bt);
bitree RestoreTree(char* pre,char* in,int q1,int q2,int z1,int z2);
int main()
{
char pre[10] = {"DBACEGF"},in[10] = {"ABCDEFG"};
bitree bt= RestoreTree(pre,in,0,6,0,6);
Postorder(bt);
return 0;
}
bitree RestoreTree(char* pre,char* in,int q1,int q2,int z1,int z2)
{
bitree bt = (bitree)malloc(sizeof(bitnode));
bt->lchild = bt->rchild = NULL;
bt->data = pre[q1];
for(int i = z1;i<=z2;i++)
{
if(in[i]==pre[q1])
{
if(i!=z1)
bt->lchild = RestoreTree(pre,in,q1+1,q1+i-z1,z1,i-1);
if(i!=z2)
bt->rchild = RestoreTree(pre,in,q1+i-z1+1,z2,i+1,z2);
break;
}
}
return bt;
}
void Postorder(bitree bt)
{
if(bt->lchild!=NULL)
Postorder(bt->lchild);
if(bt->rchild)
Postorder(bt->rchild);
printf("%c",bt->data);
}
??代码和之前一样可以简化,简化以后,不需要建树,也可以进行后序遍历。
#include<stdio.h>
#include<stdlib.h>
typedef struct BiTree{
int data;
struct BiTree* lchild;
struct BiTree* rchild;
}bitnode,*bitree;
bitree RestoreTree(char* pre,char* in,int q1,int q2,int z1,int z2);
int main()
{
char pre[10] = {"DBACEGF"},in[10] = {"ABCDEFG"};
RestoreTree(pre,in,0,6,0,6);
return 0;
}
bitree RestoreTree(char* pre,char* in,int q1,int q2,int z1,int z2)
{
for(int i = z1;i<=z2;i++)
{
if(in[i]==pre[q1])
{
if(i!=z1)
RestoreTree(pre,in,q1+1,q1+i-z1,z1,i-1);
if(i!=z2)
RestoreTree(pre,in,q1+i-z1+1,z2,i+1,z2);
break;
}
}
printf("%c",pre[q1]);
}
标签:i+1 因此 \n 中序遍历 class break 构建 str 简化
原文地址:https://www.cnblogs.com/kevinbruce656/p/10027802.html