题意如下:
03-2 列表叶 (25)
如果有一棵树,你应该按自上而下、从左到右排列所有叶子。
输入规范:
每个输入文件包含一个测试案例。对于每个案例,第一行给出一个正整数N (≤10)这是树上的节点总数-因此节点编号从0到N−1.然后N行跟随,每个对应于一个节点,并给出节点的左右子的指数。如果孩子不存在,将放置一个"-"的位置。任何一对孩子都被一个空间隔开。
输出规格:
对于每个测试案例,以自上而下、从左到右的顺序以一行打印所有叶子的指数。任何相邻数字之间必须正好有一个空格,**并且行尾没有额外的空格**。
示例输入:
8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6
样本输出:
4 1 5
注意:输入的每一行是按照从0号结点开始到N-1号结点的左右孩子
//思路:首先定义一个树结点的数组结构体,将二维树转换成一维数组的形式进行存储,该结构体定义为数组形式,结构体数组的下标对应着该结点编号,该结构体中存储着该结点的左右孩子的编号。然后进行输入。因为要从上到下,从左到右输出叶子节点,所以采用中序遍历的方法实现输出,这个时候就要定义队列进行存储和遍历树。
#include<stdio.h>
struct TNode{//定义树结点
int left;//左孩子
int right;//右孩子
}T[10];//因为结点最多有十个
int main(){
int N,i=0,book[10]={0},flag=0;//book用于查找头结点,flag用于判断是否是第一个结点用来输出空格
int front=0,rear=0,Q[10];//定义队,front=0,rear=0分别为头和尾
char l,r;//因为当没有左右孩子的时候会输入'-',所以先定义一个char类型,再进行判断让类型转换赋值给结构体
scanf("%d\n",&N);//输出结点个数
if(N){//注意后面要加上"\n"否则换行符会被当做字符输出
for(i=0;i<N;i++){//将数据存储在结点当中
scanf("%c %c\n",&l,&r);//输出左右孩子
if(l!='-')
T[i].left=l-'0';//类型转换
else
T[i].left=-1;//如果没有孩子就赋值为-1
if(r!='-')
T[i].right=r-'0';
else
T[i].right=-1;
}
}
for(i=0;i<N;i++)//寻找根结点,因为根结点没有双亲,不是谁的孩子,所以在输入从0到N-1个数字中不会出现根结点的编号,所以使用遍历输入的左右孩子,如果,左右孩子不为空就将其标记为1,然后再遍历看标记数组中哪一个为0,为0的那个数组元素的下标就是根结点
{
if(T[i].left!=-1)
book[T[i].left]=1;
if(T[i].right!=-1)
book[T[i].right]=1;
}
for(i=0;i<N;i++){
if(book[i]==0){
Q[front]=i;//将根结点入队
rear++;//将尾指针后移到1
break;
}
}
while(rear-front){//如果队列不为空就执行循环
if(T[Q[front]].right==-1&&T[Q[front]].left==-1){//首先判断左右孩子是否为空,如果都为空那么就是叶子结点,就将其输出
if(flag)//flag在初始化的时候为0,刚开始的时候输出第一个叶子节点,flag=0,所以不会输出空格,在输出第一个结点之后就将flag定为1,之后的叶子结点进行输出的时候都会先输出空格。达到末尾没有空格输出的结果
printf(" ");
printf("%d",Q[front]);
flag=1;
}
else{//如果有左右孩子就将其入队
if(T[Q[front]].left!=-1)
Q[rear++]=T[Q[front]].left;
if(T[Q[front]].right!=-1)
Q[rear++]=T[Q[front]].right;
}
front++;//将前面的结点不断出队,进行判断下一结点是否为叶子结点
}
return 0;
}