Description
题目来源:字节跳动测试题 给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替) 例如: 给定的二叉树是{3,9,20,15,7,#,#} 该二叉树之字形层序遍历的结果是 3 20 9 15 7输入格式
一行字符串,只包含大写字母和#。 此处采用完全二叉树的顺序存储结构。输出格式
若干行,之字形输出树的结点,每一行输出树的一层。输入样例
ABC###D##输出样例
A C B D
嗯……说实话,这道题把我给看傻了,我想着二叉树不就只有先序遍历、中序遍历和后序遍历吗?怎样调用这三个函数才能实现之字形输出呢?
我发现我想不出来,于是就打开了CSDN,找到了一个作者认为很“笨”而我认为很绝妙的方法。https://blog.csdn.net/m0_52463794/article/details/117619762
那我就简单的记个笔记叭。
首先,你要知道完全二叉树的顺序存储结构是什么。没错,完全二叉树的顺序存储结构是数组,所以说我一开始想的先序、中序、后序遍历和这道题是没啥太大关系的。
然后,这道题用了一些有关二叉树的性质。我简单介绍一下。
性质1 在二叉树的第i层上至多有2^(i-1)个结点。
我们就可以知道第i层的第1个结点的下标为2^(i-1)-1,第i层的最后一个结点的下标为2^i-2。
性质2 深度为k的二叉树至多有2^k-1个结点。
通过性质2,我们可以根据结点的个数来求层数。所以要先处理数组,求最后一个字母的下标。已知最后一个字母的下标,也就是知道了结点的个数,设结点个数为len,令2^k-1=len,就可以求出深度k了。
性质3 具有n个结点的完全二叉树的深度为(emm,写的比较丑)
性质3可以替换性质2,这样的话就可以少写两个循环了(少写一个求最后字母下标的循环和一个求k的循环,我看的那位作者写的博客就是用的性质2,我后来翻了翻书,发现了求完全二叉树深度的这个公式)。
这是通过性质2求深度k。
int i,j,len=0,k;
for(i=0; i<100005; i++) //记录最后一个大写字母下标
{
if(s[i]<='Z' && s[i]>='A')
len=i;
}
len=len+1;//数组从0开始储存
for(k=1; ;k++) //寻找数组代表的数的最大层数
{
if(pow(2,k)-1>=len)
break;
}
这是通过性质3求深度k(可以少写很多字)
len=strlen(s);
k=log(len)/log(2)+1;
然后之字形输出的话,就定义一个flag,flag=1的时候从左往右,flag=0的时候从右往左。每次反向的时候把第i层的第一个结点下标和最后一个结点下标的值换一下就行,可能说的不清楚,看看代码就明白了。
#include <cstdio>
#include <cstring>
#include <math.h>
#include <iostream>
using namespace std;
char s[100005]={'\0'};
int main()
{
scanf("%s",s);
int i,j,len=0,k;
/*for(i=0; i<100005; i++) //记录最后一个大写字母下标
{
if(s[i]<='Z' && s[i]>='A')
len=i;
}
len=len+1;//数组从0开始储存
for(k=1; ;k++) //寻找数组代表的数的最大层数
{
if(pow(2,k)-1>=len)
break;
}*/
len=strlen(s);
k=log(len)/log(2)+1;
int flag=1;//控制方向
for(i=1; i<=k; i++) //遍历
{
int Start=pow(2,i-1)-1;//第i层第一个结点下标
int End=pow(2,i)-2;//第i层最后一个结点的下标
if(flag==1)//从左到右输出
{
for(j=Start; j<=End; j++)
{
if(s[j]!='#') printf("%c ",s[j]);
}
flag=0;//更新flag
}
else//从右到左输出
{
for(j=End; j>=Start; j--)
{
if(s[j]!='#') printf("%c ",s[j]);
}
flag=1;//更新flag
}
printf("\n");
}
return 0;
}
4.23更新
不行不行,用性质3做的话oj上过不了,用性质2就能过(也就是下面这个),我也不知道为啥。
for(i=0; i<100005; i++) //记录最后一个大写字母下标
{
if(s[i]<='Z' && s[i]>='A')
len=i;
}
len=len+1;//数组从0开始储存
for(k=1; ;k++) //寻找数组代表的数的最大层数
{
if(pow(2,k)-1>=len)
break;
}
/*len=strlen(s);
k=log(len)/log(2)+1;*/ //这个过不了