樹遍歷的應用——樹的重建
問題描述:現有兩個結點序列,分別是對同一個二叉樹進行前序遍歷和中序遍歷。請輸出該二叉樹的後序遍歷。
輸入:第一行輸入二叉樹的結點數。
第二行輸入前序遍歷的結點編號序列,相鄰編號用空格隔開。
第三行輸入中序遍歷的結點編號序列,相鄰編號用空格隔開。
輸出:在一行輸出按後序遍歷時的結點編號序列。相鄰結點用1個空格隔開。
限制:1 < 結點數< 100
樣例輸入:3
1 2 3
2 1 3
樣例輸出:2 3 1
分析:前序遍歷序列pre中依次爲根結點的編號,例如,pre[] = {1, 2, 3, 4, 5, 7, 8}
在中序遍歷序列in中, in[] = {3, 2, 5, 4, 6, 1, 8, 7},從而序列in中根結點1左邊的序列
3, 2, 5, 4, 6爲根結點1的左子樹,根結點右邊的序列8,7爲右子樹。
這樣重建樹的時候,可以用遞歸的方式,實現樹的後序遍歷。
#include <cstdio>
#include <cstring>
const int MAX = 10000;
int n, pos, npost;//npost後序遍歷序列中的結點個數
int pre[MAX], in[MAX], post[MAX];
void rec(int left, int right);
void solve();
int main()
{
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
while (scanf("%d", &n) != EOF) {
for (int i = 0; i < n; i++)
scanf("%d", &pre[i]);
for (int i = 0; i < n; i++)
scanf("%d", &in[i]);
solve();
}
return 0;
}
void rec(int left, int right)
{
if (left >= right)
return;
int root = pre[pos++]; //取出前序遍歷中的根結點
int mid;
//尋找中序遍歷序列中的根結點位置
for (mid = 0; in[mid] != root; mid++)
;
rec(left, mid); //重建左子樹
rec(mid + 1, right); //重建右子樹
post[npost++] = root;//將當前根結點放入後序遍歷序列中
}
void solve()
{
pos = npost = 0;
rec(0, n);
for (int i = 0; i < n; i++) {
if (i) printf(" ");
printf("%d", post[i]);
}
printf("\n");
return;
}