UVA 548(DFS)+二叉树遍历

来源:互联网 发布:亿网科技域名 编辑:程序博客网 时间:2024/05/29 04:46

Description
Download as PDF
You are to determine the value of the leaf node in a given binary tree that is the terminal node of a path of least value from the root of the binary tree to any leaf. The value of a path is the sum of values of nodes along that path.
Input
The input file will contain a description of the binary tree given as the inorder and postorder traversal sequences of that tree. Your program will read two line (until end of file) from the input file. The first line will contain the sequence of values associated with an inorder traversal of the tree and the second line will contain the sequence of values associated with a postorder traversal of the tree. All values will be different, greater than zero and less than 10000. You may assume that no binary tree will have more than 10000 nodes or less than 1 node.
Output
For each tree description you should output the value of the leaf node of a path of least value. In the case of multiple paths of least value you should pick the one with the least value on the terminal node.
Sample Input
3 2 1 4 5 7 6
3 1 2 5 6 7 4
7 8 11 3 5 16 12 18
8 3 11 7 16 18 12 5
255
255
Sample Output
1
3
255

这道题的题意是根据中序遍历及后序遍历来推出树的结构,并找出一个叶子结点,使其到根节点的加权值最小。

前中后遍历区别是遍历根节点的时间,前是先遍历根节点,中是中间遍历根节点,后是最后遍历根节点。

  1. 中序遍历:先将左子树与右子树分别当成一个整体,先遍历左子树,再读取根节点,再遍历右子树。递归遍历,遍历左子树、右子树的时候,把子树的左子树、右子树分别当作一个整体,一层层遍历,直到子树是叶子结点。
  2. 后序遍历:与中序遍历相似,不同处是先遍历左子树,再遍历右子树,再读取根节点。
  3. 前序遍历:先读取根结点,再遍历左子树,再遍历右子树。

通过中序遍历和后序遍历推树的结构:
由于后序遍历是最后遍历根节点,所以后序遍历序列最后一个是根节点。知道根节点后再根据中序遍历就能知道二叉树的左子树和右子树。再用同样的方法知道左、右子树的结构。递归,直到树的结构清晰,换句话说,就是遍历到左右子树是叶子节点。
代码实现:

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;}

DFS

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);}

题目代码:

#include <iostream>#include <cstdio>#include <sstream>#include <algorithm>#include <string>using namespace std;const int maxv = 10000 + 10;int in_order[maxv], post_order[maxv], lch[maxv], rch[maxv];int n;bool read_list(int *a){    string line;    if (!getline (cin, line)) return false;//因为一行是一个整体,所以用getline    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;}int best_sum, best;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(){    #ifndef ONLINE_JUDGE    freopen ("in.txt", "r", stdin);    #endif // ONLINE_JUDGE    while (read_list(in_order)) {        read_list(post_order);        build (0, n - 1, 0, n - 1);        best_sum = 100000000000000;        dfs (post_order[n - 1], 0);        cout << best << endl;    }    return 0;}
0 0
原创粉丝点击