参考:二叉树——前序和中序得到后序

思路历程:

在最初敲的时候,经常会弄混preorder和midorder的元素位置。大体的思路就是在preorder中找到根节点(根节点在序列的左边),然后在midorder中找到根节点的位置index,中序序列在index左边的部分就是root的左子树,在index右边的部分就是root的右子树,接着进行递归即可。

在实现的过程中,经常会纠结一个父亲只有一个儿子的时候儿子是左儿子还是右儿子的问题,最后也通过特判root的位置解决了,但是容易混乱。

于是喂了度娘,找到了上面参考的文章,将每一棵树在先序序列的范围,和中序序列的范围作为递归时的参数,这样就很完美的解决了我上面的问题,这种方法比较重要的一点在于求出index来确定左右子树在中序和前序序列中的位置。

代码:

//
// main.cpp
// Tree2
//
// Created by wasdns on 16/12/19.
// Copyright © 2016年 wasdns. All rights reserved.
// #include <iostream>
#include <cstdio>
#include <cstring>
using namespace std; struct Node
{
int num; Node *l, *r;
}; int preorder[100005]; int midorder[100005]; int aftorder[100005]; Node *node[100005]; int n; int tot = 1; //记录aftorder /*
Ininode函数:用于初始化节点
*/
void Ininode()
{
int i; for (i = 1; i <= n; i++)
{
Node *p = new Node; p -> num = i;
p -> l = NULL;
p -> r = NULL; node[i] = p;
}
} /*
FindRoot函数:根据先序和中序建树。
*/
Node* FindRoot(int pre_l, int pre_r, int mid_l, int mid_r)
{
if (pre_r - pre_l < 0) return NULL; Node* root = new Node; /*将先序列表中最左边的节点作为root*/
root -> num = preorder[pre_l]; if (pre_l == pre_r)
{
root -> l = NULL;
root -> r = NULL; return root;
} /*在中序中找到root所在的位置,用index表示*/
int index; for (index = mid_l; index <= mid_r; index++)
{
if (midorder[index] == preorder[pre_l]) break;
} /*说明:利用index进行递归,分成左子树和右子树。 */
/*同时将先序序列和后序序列进行划分,将位置作为递归的参数。*/
root -> l = FindRoot(pre_l+1, pre_l+(index-mid_l), mid_l, index-1);
root -> r = FindRoot(pre_l+(index-mid_l)+1, pre_r, index+1, mid_r); return root;
} /*
CalAftorder函数:根据给定的树来计算后序序列
*/
void CalAftorder(Node *head)
{
if (head == NULL) return ; CalAftorder(head -> l);
CalAftorder(head -> r); aftorder[tot++] = head -> num;
} /*
CalPreorder函数:根据给定的树来计算先序序列
*/
void CalPreorder(Node *head)
{
if (head == NULL) return ; preorder[tot++] = head -> num; CalPreorder(head -> l);
CalPreorder(head -> r);
} /*
Print函数:输出先序、后序序列
*/
void Print()
{
int i; for (i = 1; i <= n; i++) {
cout << preorder[i] << " ";
} cout << endl; for (i = 1; i <= n; i++) {
cout << aftorder[i] << " ";
} cout << endl;
} int main()
{
cin >> n; Ininode(); int i; for (i = 1; i <= n; i++) {
cin >> preorder[i];
} for (i = 1; i <= n; i++) {
cin >> midorder[i];
} Node *head = new Node; head = FindRoot(1, n, 1, n); CalAftorder(head); Print(); return 0;
} /*
7
5 4 2 3 1 6 7
4 2 5 1 6 3 7
*/

找了道题试了下水:HDOJ 1710

将上面的代码中的主函数和Print函数做下修改就可以交了:

/*
Print函数:输出先序、后序序列
*/
void Print()
{
int i; for (i = 1; i <= n; i++) { cout << aftorder[i]; if (i != n) cout << " ";
} cout << endl;
} int main()
{
while(scanf("%d", &n) != EOF)
{
tot = 1; Ininode(); int i; for (i = 1; i <= n; i++) {
cin >> preorder[i];
} for (i = 1; i <= n; i++) {
cin >> midorder[i];
} Node *head = new Node; head = FindRoot(1, n, 1, n); memset(aftorder, 0, sizeof(aftorder)); CalAftorder(head); Print();
} return 0;
}

2016/12/21

DS Tree 已知先序、中序 => 建树 => 求后序的更多相关文章

  1. DS Tree 已知后序、中序 => 建树 => 求先序

    注意点: 和上一篇的DS Tree 已知先序.中序 => 建树 => 求后序差不多,注意的地方是在aftorder中找根节点的时候,是从右往左找,因此递归的时候注意参数,最好是拿纸和笔模拟 ...

  2. 已知树的前序、中序,求后序的java实现&已知树的后序、中序,求前序的java实现

    public class Order { int findPosInInOrder(String str,String in,int position){ char c = str.charAt(po ...

  3. TZOJ 3209 后序遍历(已知中序前序求后序)

    描述 在数据结构中,遍历是二叉树最重要的操作之一.所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问. 这里给出三种遍历算法. 1.中序遍历的递归算法定义:  ...

  4. Tree Recovery(前序中序求后序)

    Tree Recovery Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14640   Accepted: 9091 De ...

  5. HDU1710---树(知前序遍历与中序遍历 求后序遍历)

    知前序遍历与中序遍历 求后序遍历 #include<iostream> #include<cstring> #include<queue> #include< ...

  6. hdu1710-Binary Tree Traversals (由二叉树的先序序列和中序序列求后序序列)

    http://acm.hdu.edu.cn/showproblem.php?pid=1710 Binary Tree Traversals Time Limit: 1000/1000 MS (Java ...

  7. HDU 1710 二叉树遍历,输入前、中序求后序

    1.HDU  1710  Binary Tree Traversals 2.链接:http://acm.hust.edu.cn/vjudge/problem/33792 3.总结:记录下根结点,再拆分 ...

  8. python实现根据前序与中序求后序

    我就不板门弄斧了求后序 class Tree(): def __init__(self,x): self.value=x self.left=None self.right=None class So ...

  9. PAT (Advanced Level) 1136~1139:1136模拟 1137模拟 1138 前序中序求后序 1139模拟

    1136 A Delayed Palindrome(20 分) 题意:给定字符串A,判断A是否是回文串.若不是,则将A反转得到B,A和B相加得C,若C是回文串,则A被称为a delayed palin ...

随机推荐

  1. js动画实现透明度动画

    在本次实例中,由于一般主流的浏览器对于透明度opacity最大值为1,但是在IE6最大值是100,此次例子是按主流浏览器的透明度来算的,所以定义的是小数,也可以定义为整数为单位,在运算的时候遇到主流的 ...

  2. 请将 php.ini 中的 short_open_tag 设置为 On,否则无法继续安装。

    安装的wamp套件,访问http://localhost/Discuz/install/index.PHP进行安装操作,提示 对不起,请将 php.ini 中的 short_open_tag 设置为 ...

  3. 代码审查工具StyleCop

    “代码审查”或是“代码评审”(Code Review),这是一个流程,当开发人员写好代码后,需要让别人来review一下他的代码,这是一种有效发现BUG的方法.由此,我们可以审查代码的风格.逻辑.思路 ...

  4. Java NIO非阻塞理论学习

    Java NIO和阻塞IO的区别: 阻塞I/O在调用InputStream.read()方法时是阻塞的,它会一直等到数据到来时(或超时)才会返回:同样,在调用ServerSocket.accept() ...

  5. UVA 11427 (概率DP+期望)

    题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=35396 题目大意:每晚打游戏.每晚中,赢一局概率p,最多玩n局, ...

  6. Spoj 10628. Count on a tree 题解

    题目大意: 给定一棵n个点的树,每个点有一个权值,m个询问,每次询问树上点x到点y的路径上的第k小数. 思路: dfs后给每个节点一个dfs序,以每个点在他父亲的基础上建立主席树,询问时用(点x+点y ...

  7. BZOJ1858[Scoi2010]序列操作 题解

    题目大意: 有一个01序列,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0:1 a b 把[a, b]区间内的所有数全变成1:2 a b 把[a,b]区间 ...

  8. Android PhoneGap 利用 Activity 实现 CordovaInterface

    1.修改main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns ...

  9. topcoder SRM 610 DIV2 TheMatrix

    题目的意思是给一个01的字符串数组,让你去求解满足棋盘条件的最大棋盘 棋盘的条件是: 相邻元素的值不能相同 此题有点像求全1的最大子矩阵,当时求全1的最大子矩阵是用直方图求解的 本题可以利用直方图求解 ...

  10. 洛谷 P1462 通往奥格瑞玛的道路 Label: 最小化最大值 && spfa (存多条边示例)

    题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛 题目描述 在艾泽拉斯, ...