DS Tree 已知先序、中序 => 建树 => 求后序
参考:二叉树——前序和中序得到后序
思路历程:
在最初敲的时候,经常会弄混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 已知先序、中序 => 建树 => 求后序的更多相关文章
- DS Tree 已知后序、中序 => 建树 => 求先序
注意点: 和上一篇的DS Tree 已知先序.中序 => 建树 => 求后序差不多,注意的地方是在aftorder中找根节点的时候,是从右往左找,因此递归的时候注意参数,最好是拿纸和笔模拟 ...
- 已知树的前序、中序,求后序的java实现&已知树的后序、中序,求前序的java实现
public class Order { int findPosInInOrder(String str,String in,int position){ char c = str.charAt(po ...
- TZOJ 3209 后序遍历(已知中序前序求后序)
描述 在数据结构中,遍历是二叉树最重要的操作之一.所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问. 这里给出三种遍历算法. 1.中序遍历的递归算法定义: ...
- Tree Recovery(前序中序求后序)
Tree Recovery Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14640 Accepted: 9091 De ...
- HDU1710---树(知前序遍历与中序遍历 求后序遍历)
知前序遍历与中序遍历 求后序遍历 #include<iostream> #include<cstring> #include<queue> #include< ...
- hdu1710-Binary Tree Traversals (由二叉树的先序序列和中序序列求后序序列)
http://acm.hdu.edu.cn/showproblem.php?pid=1710 Binary Tree Traversals Time Limit: 1000/1000 MS (Java ...
- HDU 1710 二叉树遍历,输入前、中序求后序
1.HDU 1710 Binary Tree Traversals 2.链接:http://acm.hust.edu.cn/vjudge/problem/33792 3.总结:记录下根结点,再拆分 ...
- python实现根据前序与中序求后序
我就不板门弄斧了求后序 class Tree(): def __init__(self,x): self.value=x self.left=None self.right=None class So ...
- 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 ...
随机推荐
- PDA手持移动POS销售开单软件(网络版)、PDA手持设备小票机
背景描述: 一家大中型批发及门店销售企业,经销多种冻食品,业务范围覆盖周边众多区域和城市.成立以来,随着业务量的扩大,产品销售分两大渠道:多门店销售和仓库批发,各门店每天都有大量的零散客户和老客户进行 ...
- jquery mousewheel
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js&quo ...
- HDU4888 Redraw Beautiful Drawings(最大流唯一性判定:残量网络删边判环)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4888 Description Alice and Bob are playing toget ...
- Sqlserver自定义函数Function
一.FUNCTION: 在sqlserver2008中有3中自定义函数:标量函数/内联表值函数/多语句表值函数,首先总结下他们语法的异同点: 同点:1.创建定义是一样的: ...
- 03_Swift2基础之基本数据类型+相互转换
1. 整数 整数就是没有小数部分的数字,比如`42`和`-23`.整数可以是`有符号`(正.负.零)或者`无符号`(正.零). Swift 提供了,,和位的有符号和无符号整数类型.这些整数类型和 C语 ...
- iOS之03-类的合理设计
以下代码为了充分学习理解 类与对象 类与对象的定义 类就是将事物的共有属性和方法抽离出来形成的:类是现实世界或思维世界中的实体在计算机中的反映,它将数据以及这些数据上的操作封装在一起. 对象是具有类类 ...
- unity MenuAnim.MoveTo
移动函数,第一个参数是gameobject,第二个参数是pos,第三个参数是时间,第四个参数延迟 MenuAnim.MoveTo(title, new Vector3(1, 0.7f, 0), 0.5 ...
- 一道常被人轻视的前端JS面试题(转)
分享下我曾经出过的一道面试题,此题是我出的一套前端面试题中的最后一题,用来考核面试者的JavaScript的综合能力,很可惜到目前为止的将近两年中,几乎没有人能够完全答对,并非多难只是因为大多面试者过 ...
- bzoj2962 序列操作 题解
题目大意: 有一个长度为n的序列,有三个操作1.I a b c表示将[a,b]这一段区间的元素集体增加c,2.R a b表示将[a,b]区间内所有元素变成相反数,3.Q a b c表示询问[a,b]这 ...
- 使用TCMalloc优化OpenResty
1.安装依赖包 yum -y install wget gcc gcc-c++ -y 2.安装libunwind库可以从http://ftp.twaren.net/Unix/NonGNU//libun ...