历届试题 横向打印二叉树
时间限制:1.0s 内存限制:256.0MB
问题描述
二叉树可以用于排序。其原理很简单:对于一个排序二叉树添加新节点时,先与根节点比较,若小则交给左子树继续处理,否则交给右子树。
当遇到空子树时,则把该节点放入那个位置。
比如,10 8 5 7 12 4 的输入顺序,应该建成二叉树如下图所示,其中.表示空白。
...|-12
10-|
...|-8-|
.......|...|-7
.......|-5-|
...........|-4
10-|
...|-8-|
.......|...|-7
.......|-5-|
...........|-4
本题目要求:根据已知的数字,建立排序二叉树,并在标准输出中横向打印该二叉树。
输入格式
输入数据为一行空格分开的N个整数。 N<100,每个数字不超过10000。
输入数据中没有重复的数字。
输出格式
输出该排序二叉树的横向表示。为了便于评卷程序比对空格的数目,请把空格用句点代替:
样例输入1
10 5 20
样例输出1
...|-20
10-|
...|-5
10-|
...|-5
样例输入2
5 10 20 8 4 7
样例输出2
.......|-20
..|-10-|
..|....|-8-|
..|........|-7
5-|
..|-4
..|-10-|
..|....|-8-|
..|........|-7
5-|
..|-4
需要解决的主要问题
数据储存
使用二叉树(目前我只想到了这个)
打印规则
因为打印是先左在、右先上后下的
所以应该针对每一行进行分发现
发现:对于一条右支,
如果它前一层是右支,那么它并未被上一层"盖住",打印的是 "..." ;
如果它前一层是左支,那么它被"盖住",打印的是 "..|" 。
之后继续,如果前一层是左支,那么再前一层是右支的话才打印 “..|”。
直到 到第一层。
(左支同理)
对于一行,先扫描底层(打印靠右),再扫描高层(打印靠左)。
然而打印顺序是先左再右
所以需要一个栈来存储数据
或者 使用嵌套函数
对于左右支的判断,我选择用数组 flag 记录当前状态的左右支情况。
用 0 1 来表示左右支,下标对应层数
但是加上需要根据数值的位数改变 '.' 的数量
所以决定 用正负表示左右支 用flag大小表示长度
对于遍历树,用嵌套函数可以方便的遍历两个分支。
- 数据储存
- 打印规则
数据储存
使用二叉树(目前我只想到了这个)
打印规则
因为打印是先左在、右先上后下的
所以应该针对每一行进行分发现
发现:对于一条右支,
如果它前一层是右支,那么它并未被上一层"盖住",打印的是 "..." ;
如果它前一层是左支,那么它被"盖住",打印的是 "..|" 。
之后继续,如果前一层是左支,那么再前一层是右支的话才打印 “..|”。
直到 到第一层。
(左支同理)
对于一行,先扫描底层(打印靠右),再扫描高层(打印靠左)。
然而打印顺序是先左再右
所以需要一个栈来存储数据
或者 使用嵌套函数
对于左右支的判断,我选择用数组 flag 记录当前状态的左右支情况。
用 0 1 来表示左右支,下标对应层数
但是加上需要根据数值的位数改变 '.' 的数量
所以决定 用正负表示左右支 用flag大小表示长度
对于遍历树,用嵌套函数可以方便的遍历两个分支。
#include <stdio.h>
#include <stdlib.h>
#define TYPE struct NODE
TYPE
{
TYPE *L;
TYPE *R;
int atom;
};
void Del(TYPE *p)
{
if(p==NULL)return ;
Del(p->L);
Del(p->R);
free(p);
}
void Add(TYPE *p, TYPE *padd)
{
if(padd->atom < p->atom)
{
if(p->L!=NULL)
Add(p->L, padd);
else
p->L=padd;
}
else
{
if(p->R!=NULL)
Add(p->R, padd);
else
p->R=padd;
}
}
TYPE *Create(int num)
{
TYPE *p=(TYPE *)malloc(sizeof(TYPE));
p->L=NULL;
p->R=NULL;
p->atom=num;
return p;
}
int lenofnum(int num)
{
if(num<10)return 1;
return 1+lenofnum(num/10);
}
int flag[100];
void _f_pri(int m, int mod)
{
if(m<0)return _f_pri(-m, mod);
int z;
for(z=0; z<m-mod; z++)
printf(".");
if(mod==1)printf("|");
}
void _f(int level, int baseflag)
{
if( level<0 )return ;
int mod=0;
//if( baseflag==0 || ( (flag[level]>>31)^(baseflag>>31) == -1 ) ) // ? 50 10 40 20 15 22 3
if( baseflag==0 || (flag[level]^baseflag)<0 )
mod=1;
_f(level-1, flag[level]);
_f_pri(flag[level], mod);
}
void deal(TYPE *p, int level)
{
if(p==NULL)return ;
if(p->R!=NULL)
{
flag[level]=((level==0)?2:3)+lenofnum(p->atom);
deal(p->R, level+1);
}
if(level!=0)_f(level-1, 0);
if(level!=0)printf("-");
printf("%d", p->atom);
if(p->R==NULL && p->L==NULL)printf("\n");
else printf("-|\n");
if(p->L!=NULL)
{
flag[level]=-((level==0?2:3)+lenofnum(p->atom));
deal(p->L, level+1);
}
}
int main()
{
int n=0, j, temp;
char ch;
TYPE *proot=NULL;
for(j=0; j<100; j++)flag[j]=0;
do
{
scanf("%d%c", &temp, &ch);
if(++n==1)proot=Create(temp);
else Add(proot, Create(temp));
}while(ch==' ');
deal(proot, 0);
Del(proot);
return 0;
}
历届试题 横向打印二叉树