二叉树四种遍历及已知二叉树两种遍历方式求另外一种

二叉树的四种遍历:

先序遍历:根结点 --> 左子树 --> 右子树
中序遍历:左子树 --> 根结点 --> 右子树
后序遍历:左子树 --> 右子树 --> 根结点
层序遍历:一层一层的遍历,一般借助队列实现。

演示代码:
数组模拟满二叉树,不存在的结点用0表示。该种建树方式对空间消耗大,且建树时为了维持满二叉树的特性,还需用0表示不存在的结点。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int tree[maxn],ind=0;
void dfs1(int root)//先序,根结点 --> 左子树 --> 右子树
{
	if(tree[root]!=0)//存在结点
	{
		printf("%d\t",tree[root]);
		dfs1((root<<1)+1);
		dfs1((root<<1)+2);
	}
}
void dfs2(int root)//中序,左子树 --> 根结点 --> 右子树
{
	if(tree[root]!=0)
	{
		dfs2((root<<1)+1);
		printf("%d\t",tree[root]);
		dfs2((root<<1)+2);
	}
}
void dfs3(int root)//后序,左子树 --> 右子树 --> 根结点
{
	if(tree[root]!=0)
	{
		dfs3((root<<1)+1);
		dfs3((root<<1)+2);
		printf("%d\t",tree[root]);
	}
}
void bfs(int root)//层序,利用队列实现
{
	queue<int> q;
	q.push(root);
	while(!q.empty())
	{
		int root=q.front();q.pop();
		if(tree[root]!=0)
		{
			printf("%d\t",tree[root]);
			q.push((root<<1)+1);//左孩子入队列
			q.push((root<<1)+2);//右孩子入队列
		}
	}
	printf("\n");
}
int main()
{
	while(cin>>tree[ind])
		ind++;
	dfs1(0);printf("\n");//先序遍历
	dfs2(0);printf("\n");//中序遍历
	dfs3(0);printf("\n");//后序遍历
	bfs(0);层序遍历
	return 0;
}

已知二叉树两种遍历方式求另外一种:

预备知识:二叉树面试题–已知二叉树的两种遍历序列,求出另一种遍历序列

根据中序和先序求后序:洛谷P1827
在这里插入图片描述

输入样例:
ABEDFCHG
CBADEFGH 

输出样例:
AEFDBHGC

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5;
char a[maxn],b[maxn];
void dfs(int al,int ar,int bl,int br)//根据先序(根-->左-->右)的根不断分割中序
{
	if(al>ar || bl>br)
		return ;
	for(int i=al;i<=ar;i++)
	{
		if(a[i]== b[bl])
		{
			dfs(al,i-1,bl+1,bl+i-al);//左子树
			dfs(i+1,ar,bl+i-al+1,br);//右子树
			printf("%c",a[i]);
		}
	}
	return ;
}
int main()
{
	scanf("%s%s",&a,&b);//中序,先序
	int len=strlen(a)-1;
	dfs(0,len,0,len);//求后序
	return 0;
}

根据中序和后序求先序:洛谷P1030
在这里插入图片描述

输入样例:
BADC
BDCA

输出样例:
ABCD

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5;
char a[maxn],b[maxn];
void dfs(int al,int ar,int bl,int br)//根据后序(左-->右-->根)的根不断划分中序
{
	if(al>ar || bl>br)
		return ;
	for(int i=al;i<=ar;i++)
	{
		if(a[i]==b[br])
		{
			printf("%c",a[i]);
			dfs(al,i-1,bl,bl+i-al-1);//左子树
			dfs(i+1,ar,bl+i-al,br-1);//右子树
		}
	}
}	
int main()
{
	scanf("%s%s",&a,&b);//中序后序
	int len=strlen(a)-1;
	dfs(0,len,0,len);//求先序
	return 0;
}

根据先序和后序求中序序列个数:洛谷P1229

注:给定一棵二叉树的前序和后序,不能确定其唯一的中序遍历序列(即不能确定一棵树)。原因是:某个结点只有一棵子树根据前序和后序不能确定是左子树还是右子树,此时存在两种中序遍历。
所以将问题转化为找只有一个儿子的结点的个数。(前序中出现AB,后序中出现BA,则这个结点只有一个儿子)每个这类结点有两种中序遍历(儿子在左或儿子在右),总中序遍历数为 2这类结点个数种。
在这里插入图片描述

输入样例:
abc                           
cba

输出样例:
4

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5;
char a[maxn],b[maxn];	
int main()
{
	scanf("%s%s",&a,&b);
	int len=strlen(a),ans=0;
	for(int i=0;i<len-1;i++)
		for(int j=1;j<len;j++)
			if(a[i]==b[j]&&a[i+1]==b[j-1])
				ans++; //只有一个儿子的结点个数
	printf("%lld\n",(1LL)<<ans);//中序遍历种数 2^ans
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值