二叉搜索的遍历及建树(先序,中序,后序)

本文介绍二叉树的基本概念及其三种遍历方式:先序、中序和后序。重点讲解如何根据先序遍历和中序遍历构造二叉树,并给出一个具体的编程实例,帮助读者深入理解二叉树的存储结构及遍历算法。
  • 什么是二叉树?
  • 二叉树的每个节点最多有两个子节点,分别是左孩子,右孩子,以他们为根的子树称为左子树,右子树
  • 二叉树大家应该都有了解,博主立志做一个庸俗 通俗 善解人意的好博主,详细的二叉树结构就教给大家去另学了。
  • 简单说一句,二叉树可以分为满二叉树,完全二叉树,以及~~~。

重要的知识点来了:

二叉树的遍历有三种,俗称先序,中序,后序;
先序遍历以父节点优先,以父节点,左儿子,右儿子的顺序遍历。
中序遍历以父节点为中,以左儿子,右儿子,右儿子的顺序遍历。
后序遍历以父节点最后,以左儿子,右儿子,父节点的顺序遍历。
但是!以上统统不是重点
重点是,你要记住一个结论:
只要知道中序遍历+任意另一个遍历,就可以把这颗二叉树构造出来。

至于为什么,由于博主懒得 没有画图工具。就不去证明了。
我们就来看看怎么实现。

  • 首先,二叉树是一颗很容易操(作)的树。
  • 二叉树的存储结构: 一般用指针来实现:
struct node{
  int value;
  node *l,*r;
};
  • 用new来新建节点,使用完后记得delete释放。

以hdu1710为例:

A binary tree is a finite set of vertices that is either empty or
consists of a root r and two disjoint binary trees called the left and
right subtrees. There are three most important ways in which the
vertices of a binary tree can be systematically traversed or ordered.
They are preorder, inorder and postorder. Let T be a binary tree with
root r and subtrees T1,T2.

In a preorder traversal of the vertices of T, we visit the root r
followed by visiting the vertices of T1 in preorder, then the vertices
of T2 in preorder.

In an inorder traversal of the vertices of T, we visit the vertices of
T1 in inorder, then the root r, followed by the vertices of T2 in
inorder.

In a postorder traversal of the vertices of T, we visit the vertices
of T1 in postorder, then the vertices of T2 in postorder and finally
we visit r.

Now you are given the preorder sequence and inorder sequence of a
certain binary tree. Try to find out its postorder sequence.

Input The input contains several test cases. The first line of each
test case contains a single integer n (1<=n<=1000), the number of
vertices of the binary tree. Followed by two lines, respectively
indicating the preorder sequence and inorder sequence. You can assume
they are always correspond to a exclusive binary tree.

Output For each test case print a single line specifying the
corresponding postorder sequence.

Sample Input

9 1 2 4 7 3 5 8 9 6 4 7 2 1 8 5 9 3 6

Sample Output

7 4 2 8 9 5 6 3 1

题意:输入一棵树的先序遍历和中序遍历,求后序遍历。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<math.h>
#include<algorithm>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
#define lson 2*i    
#define rson 2*i+1    
#define LS l,mid,lson    
#define RS mid+1,r,rson    
#define UP(i,x,y) for(i=x;i<=y;i++)    
#define DOWN(i,x,y) for(i=x;i>=y;i--)    
#define MEM(a,x) memset(a,x,sizeof(a))    
#define W(a) while(a)    
#define gcd(a,b) __gcd(a,b)    
#define ll long long         
#define INF 0x3f3f3f3f    
#define EXP 1e-8    
#define lowbit(x) (x&-x)
#define Swap(a,b){int temp =a;a=b;b=temp;}
const int maxn = 1010;
int pre[maxn], in[maxn], post[maxn];
struct node {           //结构体存树
	int value;
	node* l, * r;
	node(int value = 0, node* l = NULL, node* r = NULL) :value(value), l(l), r(r) {}
};
void build(int l, int r, int& t, node* &root)        //建树,建议大家画图理解
{
	int flag = -1;
	for (int i = 1; i <= r; i++)
		if (in[i] == pre[t])
		{
			flag = i;
			break;
		}
	if (flag == -1)return;
	root= new node(in[flag]);// 新建节点。
	t++;
	if (flag > l) build(l, flag - 1, t, root->l);    //新建节点大于左区间时,建左子树。
	if (flag < r) build(flag + 1, r, t, root->r);    
}
int k=1;
void postorder(node* root) {
	if (root != NULL)
	{
		postorder(root->l);  //判断左子树为空不走,和到达左子树为空返回是一样的。
		postorder(root->r);  
		post[k++] = root->value;
	}
	
}
void remove_tree(node* root)   //释放空间
{
	if (root == NULL)return;
	remove_tree(root->l);
	remove_tree(root->r);
	delete root;
}
int main() 
{
	int n;
	while (cin >> n)
	{
		for (int i = 1; i <= n; i++)
		cin >> pre[i];
	for (int i = 1; i <= n; i++)
		cin >> in[i];
	node* root;
	int t = 1;
	build(1, n,t , root);
	k = 1;
	postorder(root);
	for (int i = 1; i < k-1; i++)
		cout << post[i] << ' ';
	cout << post[k - 1] << endl;
	remove_tree(root);
	}
	return 0;
}
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值