其實,並不是已知隨意兩種遍歷結果,就能還原二叉樹的,只有已知先序和中序或中序和後序,才能還原二叉樹。
1、已知先序:ABCDEFGH,中序:BDCEAFHG,求後序。那麼在先序裏面,第一個點A肯定是根節點,然後在中序裏找到A的位置,劃分成兩部分,左邊爲BDCE,右邊爲FHG,那麼A的左子樹上肯定是BDCE,在先序裏面B的位置最靠前,那麼B就是BDCE這四個點的根節點,然後繼續劃分,B的左邊沒有節點了,那麼DCE就全在B的右子樹上,然後按照剛纔找根節點的方法繼續找就可以了,直到葉子節點。
在找某幾個點的組合中根節點的時候,根據先序找對應下標最小的。
#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
int pos[30], l[30], r[30];
char pre[30], in[30];
void dfs(int left, int right, int root, int f, int dir) {
if(left > right) return ;
if(left == right) {
if(f != -1 && dir != -1) {
if(dir == 0) {
l[f] = in[left] - 'A';
} else {
r[f] = in[left] - 'A';
}
}
return ;
}
int id = pos[pre[root] - 'A'];
int x = in[id] - 'A';
if(f != -1 && dir != -1) {
if(dir == 0) {
l[f] = x;
} else {
r[f] = x;
}
}
dfs(left, id - 1, root + 1, x, 0);
dfs(id + 1, right, root + 1 + id - left, x, 1);
}
void post_order(int x) {
if(l[x] != -1) post_order(l[x]);
if(r[x] != -1) post_order(r[x]);
printf("%c", x + 'A');
}
int main() {
scanf("%s%s", pre, in);
int len = strlen(in);
for(int i = 0; i < len; i++) {
int x = in[i] - 'A';
pos[x] = i;
}
memset(l, -1, sizeof l);
memset(r, -1, sizeof r);
dfs(0, len - 1, 0, -1, -1);
post_order(pre[0] - 'A');
printf("\n");
return 0;
}
2、已知後序:DECBHGFA,中序:BDCEAFHG,求先序。在後序裏面A必定是根節點,那麼在中序裏面找到A,劃分爲左右子樹,過程跟上面說過的類似,只不過在找某幾個點的根節點的時候,是在後序裏面找位置最靠後的,即對應下標最大的。
#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
int pos[30], l[30], r[30];
char post[30], in[30];
void dfs(int left, int right, int root, int f, int dir) {
if(left > right) return ;
if(left == right) {
if(f != -1 && dir != -1) {
if(dir == 0) {
l[f] = in[left] - 'A';
} else {
r[f] = in[left] - 'A';
}
}
return ;
}
int id = pos[post[root] - 'A'];
int x = in[id] - 'A';
if(f != -1 && dir != -1) {
if(dir == 0) {
l[f] = x;
} else {
r[f] = x;
}
}
dfs(left, id - 1, root - 1 - right + id, x, 0);
dfs(id + 1, right, root - 1, x, 1);
}
void pre_order(int x) {
printf("%c", x + 'A');
if(l[x] != -1) pre_order(l[x]);
if(r[x] != -1) pre_order(r[x]);
}
int main() {
scanf("%s%s", post, in);
int len = strlen(in);
for(int i = 0; i < len; i++) {
int x = in[i] - 'A';
pos[x] = i;
}
memset(l, -1, sizeof l);
memset(r, -1, sizeof r);
dfs(0, len - 1, len - 1, -1, -1);
pre_order(post[len - 1] - 'A');
printf("\n");
return 0;
}