对于给定的二叉树,本题要求你按从上到下、从左到右的顺序输出其所有叶节点。
首先第一行给出一个正整数 N(≤10),为树中结点总数。树中的结点从 0 到 N−1 编号。随后 N 行,每行给出一个对应结点左右孩子的编号。如果某个孩子不存在,则在对应位置给出 “-”。编号间以 1 个空格分隔。
在一行中按规定顺序输出叶节点的编号。编号间以 1 个空格分隔,行首尾不得有多余空格。
8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6
4 1 5
以样例为例,输入结点个数为8的一个树,输入的是每个节点的左右孩子,如图
画出树
1、4、5为叶子节点
可以发现:叶子节点即输入数据中没有左孩子也没有右孩子的结点
按“从上到下,从左到右”输出叶子节点
我设定了两个概念:
前驱个数:即该节点的祖先总数
水平位置:在整个树中以树根为中心的相对位置,树根的水平位置为0(作为一个左孩子就-1,右孩子就+1)
水平位置举例:
1节点的水平位置,1节点的祖先是0、2、3,3节点是根其水平位置是0,2结节点是3节点的左孩子,则2节点的水平位置为-1,0节点是2节点的左孩子,则0节点的水平位置为-2,1节点是0节点的左孩子,则1节点的水平位置为-3。
同理4节点的水平位置为0,5节点的水平位置为1。
此时再看输出:
从上到下:所有叶节点中即前驱个数少的先输出
从左到右:所有叶节点中水平位置小的先输出
综述:同等前驱个数,水平位置小的先输出;同等水平位置,前驱个数小的先输出。
知道了输入是什么,输出是什么,我们要做的就是把输入的树做好处理和保存,然后统计所有叶子结点的前驱个数和水平位置
一、 deal_tree( )
deal_tree( ):处理输入的树并保存的函数,将结果保存在结构体数组tree中
pot:当前节点就是pot节点,1节点,pot即1
input [ ]:保存pot 节点的左右孩子
#define peerless -10000//peerless绝后的,即叶子节点的左右孩子都赋值为peerless
typedef struct tree_node
{
int node;//当前节点
int left_c;//左孩子
int right_c;//又孩子
};
struct tree_node tree[15];
void deal_tree(char *input,struct tree_node *tree,int pot);
void deal_tree(char *input,struct tree_node *tree,int pot)
{
int i=0;
while(i<=1)
{
if(input[i]=='-')
{
if(i==0)
{
tree[pot].left_c=peerless;
}
else
{
tree[pot].right_c=peerless;
}
}
else if(input[i]!='-')
{
if(i==0)
{
tree[pot].left_c=input[i]-'0';
}
else
{
tree[pot].right_c=input[i]-'0';
}
}
i++;
}
}
二、find_leaf( )
find_leaf( ):查找叶子节点,并进行排序和输出
p_l:保存叶子节点以及其前驱个数和水平位置
如何找前驱和确定水平位置:确定叶子节点后,因为结构体下标即叶子节点,通过遍历tree查找它的前驱,并且在查找前驱的时候,确认本身节点的位置,是左孩子则水平位置-1,是右则水平位置+1;每找到一个前驱,就将查找对象赋值为该前驱节点,继续找这个前驱的前驱。
然后排序就行了,完结撒花!
typedef struct pre_level
{
int node;
int pre;
int level;
};
struct pre_level p_l[10];
void find_leaf(struct tree_node *tree,struct pre_level *p_l,int N);
void find_leaf(struct tree_node *tree,struct pre_level *p_l,int N)
{
int i=0,j=0,k=0,z=0,pre=0,level=0;
while(i<N)
{
if(tree[i].left_c==peerless && tree[i].right_c==peerless)
{//说明 i 节点是叶子节点
pre=0;
level=0;
k=0;
j=i;
//查找前驱,确认水平位置
while(k<N)
{
if(tree[k].left_c==j)
{
pre++;
level--;
//找到前驱后将查找对象提换为该前驱,查找前驱的前驱
j=k;
k=-1;
}
else if(tree[k].right_c==j)
{
pre++;
level++;
j=k;
k=-1;
}
k++;
}
//printf("%d %d %d\n",i,pre,level);
p_l[z].node=i;
p_l[z].pre=pre;
p_l[z].level=level;
z++;
}
i++;
}
//先排前驱,小的在前
j=0;
k=0;
i=0;
pre=0;
level=0;
while(k<z)
{
j=k+1;
while(j<z)
{
if(p_l[k].pre>p_l[j].pre)
{
i=p_l[k].node;
pre=p_l[k].pre;
level=p_l[k].level;
p_l[k].node=p_l[j].node;
p_l[k].pre=p_l[j].pre;
p_l[k].level=p_l[j].level;
p_l[j].node=i;
p_l[j].pre=pre;
p_l[j].level=level;
}
j++;
}
k++;
}
//前驱相同的情况下,水平位置小的在前
j=0;
k=0;
i=0;
pre=0;
level=0;
while(k<z)
{
j=k+1;
while(j<z)
{
if(p_l[k].level>p_l[j].level && p_l[k].pre==p_l[j].pre)
{
i=p_l[k].node;
pre=p_l[k].pre;
level=p_l[k].level;
p_l[k].node=p_l[j].node;
p_l[k].pre=p_l[j].pre;
p_l[k].level=p_l[j].level;
p_l[j].node=i;
p_l[j].pre=pre;
p_l[j].level=level;
}
j++;
}
k++;
}
i=0;
//这里的注释是为了看看p_l的保存的对不对
//while(i
//{
// printf("%d %d %d\n",p_l[i].node,p_l[i].pre,p_l[i].level);
//i++;
//}
i=0;
while(i<z)
{
if(i+1!=z)
{
printf("%d ",p_l[i].node);
}
else
{
printf("%d\n",p_l[i].node);
}
i++;
}
}
#include
#include
#define peerless -10000
typedef struct tree_node
{
int node;//当前节点
int left_c;//左孩子
int right_c;//又孩子
};
struct tree_node tree[15];
typedef struct pre_level
{
int node;
int pre;
int level;
};
struct pre_level p_l[10];
void deal_tree(char *input,struct tree_node *tree,int pot);
void find_leaf(struct tree_node *tree,struct pre_level *p_l,int N);
int main()
{
int N=0,i=0;
char input[10]="";
scanf("%d",&N);
getchar();
while(i<N)
{
scanf("%c %c",&input[0],&input[1]);
getchar();
deal_tree(input,tree,i);
i++;
}
find_leaf(tree,p_l,N);
return 0;
}
void deal_tree(char *input,struct tree_node *tree,int pot)
{
int i=0;
while(i<=1)
{
if(input[i]=='-')
{
if(i==0)
{
tree[pot].left_c=peerless;
}
else
{
tree[pot].right_c=peerless;
}
}
else if(input[i]!='-')
{
if(i==0)
{
tree[pot].left_c=input[i]-'0';
}
else
{
tree[pot].right_c=input[i]-'0';
}
}
i++;
}
}
void find_leaf(struct tree_node *tree,struct pre_level *p_l,int N)
{
int i=0,j=0,k=0,z=0,pre=0,level=0;
while(i<N)
{
if(tree[i].left_c==peerless && tree[i].right_c==peerless)
{//说明 i 节点是叶子节点
pre=0;
level=0;
k=0;
j=i;
while(k<N)
{
if(tree[k].left_c==j)
{
pre++;
level--;
j=k;
k=-1;
}
else if(tree[k].right_c==j)
{
pre++;
level++;
j=k;
k=-1;
}
k++;
}
//printf("%d %d %d\n",i,pre,level);
p_l[z].node=i;
p_l[z].pre=pre;
p_l[z].level=level;
z++;
}
i++;
}
j=0;
k=0;
i=0;
pre=0;
level=0;
while(k<z)
{
j=k+1;
while(j<z)
{
if(p_l[k].pre>p_l[j].pre)
{
i=p_l[k].node;
pre=p_l[k].pre;
level=p_l[k].level;
p_l[k].node=p_l[j].node;
p_l[k].pre=p_l[j].pre;
p_l[k].level=p_l[j].level;
p_l[j].node=i;
p_l[j].pre=pre;
p_l[j].level=level;
}
j++;
}
k++;
}
j=0;
k=0;
i=0;
pre=0;
level=0;
while(k<z)
{
j=k+1;
while(j<z)
{
if(p_l[k].level>p_l[j].level && p_l[k].pre==p_l[j].pre)
{
i=p_l[k].node;
pre=p_l[k].pre;
level=p_l[k].level;
p_l[k].node=p_l[j].node;
p_l[k].pre=p_l[j].pre;
p_l[k].level=p_l[j].level;
p_l[j].node=i;
p_l[j].pre=pre;
p_l[j].level=level;
}
j++;
}
k++;
}
i=0;
//while(i
//{
// printf("%d %d %d\n",p_l[i].node,p_l[i].pre,p_l[i].level);
//i++;
//}
i=0;
while(i<z)
{
if(i+1!=z)
{
printf("%d ",p_l[i].node);
}
else
{
printf("%d\n",p_l[i].node);
}
i++;
}
}
额,测试样例我是没有的,因为拼题A改版了,再说了俺是一次过的,要啥测试样例(doge),所以说,就是晒出来秀一下,hei! hei!