UVa 548

 

 

这题就是运用了二叉树重建, 以及遍历。

二叉树的遍历:先序遍历,中序遍历,后序遍历
只要有一个中序序列再加上另一个序列就可唯一地重建原来二叉树。

先序遍历就是先访问根节点,然后再先序遍历左子树,最后先序遍历右子树。先序遍历也就是深度优先搜索(DFS)。

进行了二叉树重建之后,只要对这棵二叉树进行搜索, 取得各个路径之和,然后找出最小的那个和即可。

 

/*
题意:给出中序遍历和后序遍历,求最小路径上(从根到叶的和最小)的叶节点,如果有多个最小路径,输出最小叶节点 
思路:建树遍历
 
7 8 11 3 5 16 12 18
8 3 11 7 16 18 12 5
                     5
                7        12
                   11   16  18
                  8   3

*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<sstream>
#include<algorithm>
using namespace std;

const int N=10001;
int a[N], b[N];

struct node
{
        int v;
        node* l;
        node* r;
}nodes[N];

int nodeindex;

node* newNode()
{
        return &nodes[nodeindex++];
}

//返回根节点
node* buildTreeInPost(int len, int* in, int *post)
{
        if(len<=0) return 0;

        int root=post[len-1];
//这个输出也是dfs顺序的
//      cout<<root<<endl;
        node* nd=newNode();
        nd->v=root;

        int* p=find(in, in+len, root);
        int left_len=p-in;
        int right_len=len-left_len-1;
        nd->l=buildTreeInPost(left_len, in, post);
        nd->r=buildTreeInPost(right_len, in+left_len+1, post+left_len);
        return nd;
}

int leastsum, leastleaf;
void dfs(node* root, int sum)
{
        if(!root)
                return;

        //cout<<root->v<<endl;
        sum+=root->v;
        //叶节点
        if(!root->l && !root->r)
        {
                if(sum<leastsum || (sum==leastsum && root->v<leastleaf))
                {
                        leastsum=sum; 
                        leastleaf=root->v;
                }
        }

        if(root->l)
                dfs(root->l, sum);
        if(root->r)
                dfs(root->r, sum);
}

int main()
{
        string str1, str2;
        while(getline(cin, str1) && getline(cin, str2))
        {
                istringstream istrstr1(str1);
                istringstream istrstr2(str2);
                int i=0;
                while((istrstr1>>a[i]) && (istrstr2>>b[i]))
                        i++;

                nodeindex=0;
        //      cout<<"buildTreeInPost"<<endl;
                node* root=buildTreeInPost(i, a, b);

                leastleaf=leastsum=100000000;

        //      cout<<"dfs"<<endl;
                dfs(root, 0);
                cout<<leastleaf<<endl;
        }

    return 0;
}

 

 

由中序遍历 分别和前序遍历,后序遍历进行建树的方法:

/*
题意:给出中序遍历和后序遍历,求最小路径上(从根到叶的和最小)的叶节点,如果有多个最小路径,输出最小叶节点 
思路:建树遍历
 
in order
7 8 11 3 5 16 12 18
post order
8 3 11 7 16 18 12 5
             5
        7        12
         11     16 18
        8  3

pre order
5 7 11 8 3 12 16 18

*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<sstream>
#include<algorithm>
using namespace std;

const int N=10001;
int a[N], b[N];

struct node
{
    int v;
    node* l;
    node* r;
}nodes[N];

int nodeindex;

node* newNode()
{
    return &nodes[nodeindex++];
}

//根据中序和后序建树
//返回根节点
node* buildTreeInPost(int len, int* in, int *post)
{
    if(len<=0) return 0;

    int root=post[len-1];
//这个输出也是dfs顺序的
    cout<<root<<endl;
    node* nd=newNode();
    nd->v=root;

    int* p=find(in, in+len, root);
    int left_len=p-in;
    int right_len=len-left_len-1;
    nd->l=buildTreeInPost(left_len, in, post);
    nd->r=buildTreeInPost(right_len, in+left_len+1, post+left_len);
    return nd;
}
//根据中序和前序建树
//返回根节点
node* buildTreeInPre(int len, int* in, int* pre)
{
    if(len<=0) return 0;

    int root=pre[0];
//这个输出也是dfs顺序的
    cout<<root<<endl;
    node* nd=newNode();
    nd->v=root;

    int* p=find(in, in+len, root);
    int left_len=p-in;
    int right_len=len-left_len-1;
    nd->l=buildTreeInPre(left_len, in, pre+1);
    nd->r=buildTreeInPre(right_len, in+left_len+1, pre+left_len+1);
    return nd;
}

void dfs(node* root, int sum)
{
    if(!root)
        return;

    cout<<root->v<<endl;
    //叶节点
    if(!root->l && !root->r)
    {
        return;
    }

    if(root->l)
        dfs(root->l, sum);
    if(root->r)
        dfs(root->r, sum);
}

int main()
{
    string str1, str2;
    while(getline(cin, str1) && getline(cin, str2))
    {
        istringstream istrstr1(str1);
        istringstream istrstr2(str2);
        int i=0;
        while((istrstr1>>a[i]) && (istrstr2>>b[i]))
            i++;

        nodeindex=0;
#if 0
    //  cout<<"buildTreeInPost"<<endl;
        node* root=buildTreeInPost(i, a, b);
#else
        cout<<"buildTreeInPre"<<endl;
        node* root=buildTreeInPre(i, a, b);
#endif

        cout<<"dfs"<<endl;
        dfs(root, 0);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/cute/p/3635212.html