今天复习前面的内容的时候看到一道题UVA 548 Tree,说的是输入一个二叉树中序和后序的集合,沿着二叉树的一条边走,问叶子为多少的这条路最短。
看到这道题,中序?后序?什么玩意???不知道,百度!查了之后会了,就回来A了这题。
先给一个二叉树
二叉树前序遍历
前序遍历顺序可以简记为根左右
规则:
(1)访问根节点
(2)前序遍历左子树
(3)前序遍历右子树
(注:遍历过程为递归)
结果:ABCDEF
二叉树中序遍历
中序遍历顺序简记为左根右
规则:
(1)中序遍历左子树
(2)访问根节点
(3)中序遍历右子树
结果:CBDAFE
二叉树后序遍历
后序遍历顺序简记为左右根
规则:
(1)后序遍历左子树
(2)后序遍历右子树
(3)访问根节点
结果:CDBFEA
然后就以上面给出的UVA 548为例,熟悉一下这规则
#include<stdio.h>
#include<string.h>
#include<sstream>
#include<iostream>
using namespace std;
#define MAXN 10010
#define INF 0x3f3f3f3
int in_order[MAXN], post_order[MAXN], lch[MAXN], rch[MAXN];
int n,best,best_sum;
bool read(int *a)
{
string line;
if (!getline(cin, line))
return false;
stringstream ss(line);
n = 0;
int x;
while (ss >> x)
a[n++] = x;
return n > 0;
}
int build(int L1, int R1, int L2, int R2)
//建树过程,后序遍历中,最后一个数字肯定是该层的根节点,然后在中序遍历中找到该节点
//找到节点后,中序遍历左边为左子树,右边为右子树
//后序遍历前面相对应的数量的数字为左子树,剩下的为右子树
//即 中序遍历结构 左子树-根-右子树
// 后序遍历结构 左子树-右子树-根
{
if (L1 > R1){
return 0;
}
int root = post_order[R2];
int p = L1;
while (in_order[p] != root)
p++;
int cnt = p - L1;
lch[root] = build(L1, p - 1, L2, L2 + cnt - 1);
rch[root] = build(p + 1, R1, L2 + cnt, R2 - 1);
return root;
}
void dfs(int u, int sum)
{
sum += u;
if (!lch[u] && !rch[u]){
if (sum < best_sum || (sum == best_sum&&u < best))
{
best = u;
best_sum = sum;
}
}
if (lch[u])dfs(lch[u], sum);
if (rch[u])dfs(rch[u], sum);
}
int main()
{
while (read(in_order))
{
read(post_order);
best_sum = INF;
build(0, n - 1, 0, n - 1);
dfs(post_order[n - 1], 0);
printf("%d\n", best);
}
return 0;
}
另外,这段代码还能进行优化,不知道你想到没。
就是我们可以在建树的过程中同时记录最小值
#include<stdio.h>
#include<string.h>
#include<sstream>
#include<iostream>
using namespace std;
#define MAXN 10010
#define INF 0x3f3f3f3
int in_order[MAXN], post_order[MAXN], lch[MAXN], rch[MAXN];
int n, best, best_sum;
bool read(int *a)
{
string line;
if (!getline(cin, line))
return false;
stringstream ss(line);
n = 0;
int x;
while (ss >> x)
a[n++] = x;
return n > 0;
}
int build(int L1, int R1, int L2, int R2, int sum)
{
if (L1 > R1){
return 0;
}
int root = post_order[R2];
int p = L1;
while (in_order[p] != root)
p++;
int cnt = p - L1;
sum += root;
lch[root] = build(L1, p - 1, L2, L2 + cnt - 1, sum);
rch[root] = build(p + 1, R1, L2 + cnt, R2 - 1, sum);
if (!lch[root]&&!rch[root]){
if (sum < best_sum || (sum == best_sum&&root < best))
{
best = root;
best_sum = sum;
}
}
return root;
}
int main()
{
while (read(in_order))
{
read(post_order);
best_sum = INF;
build(0, n - 1, 0, n - 1, 0);
printf("%d\n", best);
}
return 0;
}