• POJ 2255 -- Tree Recovery


    Tree Recovery
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 16032   Accepted: 9865

    题意:

    根据二叉树的先序遍历和中序遍历,求后序遍历。

    解题思路:

    1)递归(不建树)

    可以先按照用笔和纸的形式去推导出后序序列。推导过程省略,在推导过程中我们会发现规律:

    假设 前序序列是 A B E H F C G I

     中序序列是 H E B F A C I G (图如下)

     

    每一次从前序序列里,按顺序抽取出字母就能将中序序列分割,并根据中序遍历的特性。分割后的两部分分别是 左子树 和 右子树(注意,他们也是二叉树!)

    就像这样:取A, 中序序列被分割为 左子树:H E B F  右子树 C I G

    继续取B,但是这次是对左子树:H E B F 进行分割。 分割结果是: 左子树:H E  右子树  B F

    直到不能再分割,递归会返回去到第一次使用 A 分割出来的 右子树 里继续分割

    上述整个过程都是递归,所以结合代码和用纸笔画一次会更好理解

    char *strchr(const char* _Str,char _Val)
    头文件:#include <string.h>
    功能:查找字符串_Str中首次出现字符_Val的位置
    说明:返回首次出现_Val的位置的指针,返回的地址是被查找字符串指针开始的第一个与Val相同字符的指针,如果Str中不存在Val则返回NULL
    返回值:成功则返回要查找字符第一次出现的位置,失败返回NULL
     
     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 const int maxn = 30;
     5 
     6 
     7 void Build(char *a,char *b,char *s,int n)
     8 {//a是先序遍历,b是中序遍历
     9     if(n<=0)
    10         return;
    11     else{
    12         ///记录根节点在中序遍历中的位置
    13         int k = strchr(b,a[0]) - b;
    14         ///0~k-1为左子树
    15         Build(a+1,b,s,k);
    16         ///k+1~n为右子树
    17         Build(a+k+1,b+k+1,s+k,n-k-1);
    18         s[n-1] = a[0];
    19     }
    20 }
    21 
    22 int main()
    23 {
    24     char a[maxn],b[maxn];
    25     while(cin>>a>>b)
    26     {
    27         char ans[maxn];
    28         int len = strlen(b);
    29         Build(a,b,ans,len);
    30         ans[len] = 0;///加结束符
    31         cout<<ans<<endl;
    32     }
    33     return 0;
    34 }

     2)二叉树遍历(建树)

    对二叉树的 前序遍历、中序遍历、后序遍历 均可以使用DFS来做,
    均是自上而下、自左至右遍历,区别在于打印节点的时机不同:
    [前序遍历] 从父节点进入时打印当前节点
    [中序遍历] 从左子树返回时打印当前节点
    [后序遍历] 从右子树返回时打印当前节点

     1 #include<iostream>
     2 #include<cstring>
     3 #include<string>
     4 
     5 using namespace std;
     6 const int STR_LEN = 27;//树遍历序列最大长度
     7 const int NULL_CHAR = '';//空字符
     8 
     9 ///结点结构
    10 class Node{
    11 public:
    12     char name;//节点名称
    13     Node *left;//左子树根节点
    14     Node *right;//右子树根节点
    15     Node():name(NULL_CHAR),left(NULL),right(NULL){}//初始化
    16     ~Node()
    17     {
    18         name = NULL_CHAR;
    19         delete left;left = NULL;
    20         delete right;right = NULL;
    21     }
    22 };
    23 
    24 Node* createTree(char *pro,char *in,int n)
    25 {
    26     Node *root = new Node;
    27     if(n <= 0)
    28     {
    29         return root;
    30     }else{
    31         int k = strchr(in,pro[0]) - in;//找到根节点在中序遍历中的位置
    32         root->name = pro[0];
    33         root->left = createTree(pro+1,in,k);
    34         root->right = createTree(pro+k+1,in+k+1,n-k-1);
    35         return root;
    36     }
    37 }
    38 
    39 void dfs(Node *root,char *output)
    40 {
    41     if(root == NULL)
    42     {
    43         return;
    44     }
    45     dfs(root->left,output);
    46     dfs(root->right,output);
    47     ///构造后序序列,从右子树返回时把当前的结点放到序列末尾
    48     output[strlen(output)] = root->name;
    49     //或写成:
    50     //*(output+strlen(output)) = root->name;
    51 }
    52 
    53 int main()
    54 {
    55     char pro[STR_LEN],in[STR_LEN];
    56     while(cin>>pro>>in)
    57     {
    58         int len = strlen(in);
    59         Node *root = createTree(pro,in,len);
    60         char output[STR_LEN] = {NULL_CHAR};///一定要初始化为空
    61         dfs(root,output);
    62         output[len] = 0;
    63         cout<<output<<endl;
    64         delete root;
    65     }
    66     return 0;
    67 }

    
    
  • 相关阅读:
    Java(14):面向对象、封装、继承、方法重写、多态、抽象类与接口、内部类
    Java(13):数组、Arrays类、冒泡排序
    Java(12):方法、重载、命令行传参、可变参数、方法调用
    Java(11):switch、dowhile、九九乘法表、打印质数、打印三角形
    Java(10):用户交互Scanner
    Java(9):包
    Java(8):运算符
    Java(7):变量和常量及其规范、作用域
    Mybatis 打印日志
    mysql 更新数据
  • 原文地址:https://www.cnblogs.com/yxh-amysear/p/8447153.html
Copyright © 2020-2023  润新知