zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    hdu 2196 树形dp
    codeforces 1A
    [日常摸鱼]bzoj1218[HNOI2003]激光炸弹-二维前缀
    [日常摸鱼]bzoj2724蒲公英-分块
    [日常摸鱼]关于离散化
    [OI笔记]后缀自动机
    [日常摸鱼]poj1509Glass Beads-SAM
    [日常摸鱼]bzoj1083[SCOI2005]繁忙的都市-最小生成树
    [日常摸鱼]bzoj2038[2009国家集训队]小Z的袜子-莫队算法
    [日常摸鱼]三分法
  • 原文地址:https://www.cnblogs.com/cute/p/3635212.html
Copyright © 2011-2022 走看看