最近在刷北理复试机试题,遇到个经典问题:已知后序遍历和中序遍历,求前序遍历。
参考别人博客写的代码。
原文链接:https://blog.youkuaiyun.com/u014552756/article/details/55510814
算法思想:
- 后序遍历的最后一个字符(假设为x)即为前序的第一个字符。
- 在中序遍历中x之前的为x的左子树的中序遍历,x之后的为x的右子树的中序遍历。
- 假设中序遍历中x之前的字符有n个,则对应后序遍历中前n个字符为这n个字符的后序遍历。
- 重复1-3.即用递归可以很容易做。
代码(1):直接输出结果,不需要生成树。
#include<bits/stdc++.h>
using namespace std;
char lrd[20], ldr[20];
void reverse(int l1, int r1, int l2, int r2){
int i;
if(l1 > r1)
return ;
cout<<lrd[r1]; //后序遍历最后一个位置即为根
for(i = l2; ldr[i] != lrd[r1]; i++); //找到中序遍历中根的位置
reverse(l1, l1 + i - 1 - l2, l2, i - 1); //递归遍历其左子树
reverse(l1 + i - l2, r1 - 1, i + 1, r2); //递归遍历其右子树
}
int main(){
while(cin>>lrd>>ldr){
int len = strlen(lrd);
reverse(0, len - 1, 0, len - 1);
cout<<endl;
}
}
代码(2):需要生成树记录结果。
#include<bits/stdc++.h>
using namespace std;
char a[20], b[20];
typedef struct node{
char c;
node *l;
node *r;
}node;
void dlr(node *T){
if(T == NULL)
return ;
cout<<T->c;
dlr(T->l);
dlr(T->r);
}
//递归建树
void reverse(int l1, int r1, int l2, int r2, node *&T){
if(l1 > r1 || l2 > r2)
return ;
if(T == NULL){
T = new node;
T->l = T->r = NULL;
}
int i;
T->c = a[r1];
for(i = l2; b[i] != a[r1]; i++);
reverse(l1, l1 + i - 1 - l2, l2, i - 1, T->l);
reverse(l1 + i - l2, r1 - 1, i + 1, r2, T->r);
}
int main(){
while(cin>>a>>b){
node *T = NULL;
int len = strlen(a);
reverse(0, len - 1, 0, len - 1, T);
dlr(T);
}
}