二叉树的四种遍历:
先序遍历:根结点 --> 左子树 --> 右子树
中序遍历:左子树 --> 根结点 --> 右子树
后序遍历:左子树 --> 右子树 --> 根结点
层序遍历:一层一层的遍历,一般借助队列实现。
演示代码:
数组模拟满二叉树,不存在的结点用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;
}