03-树2 List Leaves (过程讲解)

先看一下题目
Given a tree, you are supposed to list all the leaves in the order of top down, and left to right.
Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤10) which is the total number of nodes in the tree – and hence the nodes are numbered from 0 to N−1. Then N lines follow, each corresponds to a node, and gives the indices of the left and right children of the node. If the child does not exist, a “-” will be put at the position. Any pair of children are separated by a space.

Output Specification:

For each test case, print in one line all the leaves’ indices in the order of top down, and left to right. There must be exactly one space between any adjacent numbers, and no extra space at the end of the line.

Sample Input:

8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6

Sample Output:

4 1 5

题目如上,下面我们来分析一下:
给定一棵树,节点数由第一行输入决定。下边每一行读进去两个数,分别是以输入行数为下标的节点(0~N-1)的左儿子和右儿子,“-”代表无儿子,按从上到下从左到右的顺序输出叶节点。仔细一想,输出不就是层序遍历吗?!所以我们可以用队列。
所以解题思路是这样的:创建树,找到其根节点,遍历输出。

首先我们看一下main函数

int root,N;
int main(){
scanf("%d",&N);
root=CreateTree(N);//创建树
traversal(root);//层序遍历输出叶节点
return 0;
}

然后我们写一下树结构和存放树节点下标的队列结构

//根下标以及读入最大节点数
struct TreeNode{
int left,right;
}Tree[10];//最大节点数为10
struct queue{
int *data;
int front,rear;
}

因为CreateTree()函数需要读入一棵树且要返回此树的节点,所以我们还需要一个check数组来检查节点的位置。先将check数组全部置零,通过读入左儿子有儿子,当左儿子或右儿子不为‘-’时,将check数组对应的下标置为1,最后遍历check数组,判断若为1则赋给root返回,代码如下:

int CreateTree(int n){
char l,r;
int i;
int check[n];
for(i=0;i<n;i++)
	check[i]=0; 
for(i=0;i<n;i++)
{
	scanf("%c %c",&l,&r);
	getchar();//吸收掉回车,很重要!!!
	if(l!='-')
	{
		Tree[i].left=l-'0';   //l减‘0’即为整数
		check[i]=1;
	}
	else Tree[i].left=-1;     //若不存在左孩子,则为-1
	if(r!='-')
	{
		Tree[i].right=r-'0';
		check[i]=1;
	}
	else Tree[i].right=-1;
	
}
for(i=0;i<n;i++)
{
	if(!check[i])
		root=i;  //若不为0,根节点为i;
}

return root;
}

下面我们创建队列有关的操作

Queue CreateQueue(){
    Queue q=(Queue)malloc(sizeof(struct queue));
    q->index=(int*)malloc(8*sizeof(int));
    q->front=q->rear=-1;
    return q;
}
bool isEmpty(Queue q)
{
    return(q->front==q->rear);
}
void add(Queue q,int x)
{
    if((q->rear+1)%10==q->front)
    {
        return;
    }
    else
    {
        q->rear=(q->rear+1)%8;
        q->index[q->rear]=x;
    }
}
int pop(Queue q){
    if(q->front==q->rear)
    {
        return -1;
    }
    else
    {
        q->front=(q->front+1)%8;
        return q->index[q->front];
    }
}

下边构建层序遍历函数,代码如下:

void Traversal(int root1)
{
	int temp;//用来储存出队节点下标的临时变量
	Queue q=CreateQueue();
	add(q,root1);
	while(!isEmpty(q)) //若队列不空
	{
		temp=pop(q);
		if(Tree[temp].left!='-'&&Tree[temp].right!='-')
			{
				add(q,Tree[Tree[temp].left]);
				add(q,Tree[Tree[temp].right]);
			}
		else if(Tree[temp].left!='-'&&Tree[temp].right=='-')
			{
				add(q,Tree[Tree[temp].left]);
			}
		else if(Tree[temp].left=='-'&&Tree[temp].right!='-')
			{
				add(q,Tree[Tree[temp].right]);
			}
		else 
			printf("%d",temp);//输出叶节点
	}
}

输出结果如下:
在这里插入图片描述
下边附上完整代码:

#include <stdio.h>
#include <stdlib.h>
void traversal(int root2);
typedef enum {flase=0,true=1} bool;
int CreateTree(int N);

struct queue{
    int * index;
    int front,rear;
};
typedef struct queue*  Queue;

struct treeNode{
    int left,right;
}tree[8];
int N,root;
int main(){
    scanf("%d",&N);
    root=CreateTree(N);
    traversal(root);
  
    return 0;
}


int CreateTree(int n){
    char l,r;
    int i;
    int check[n];
    for(i=0;i<n;i++)
        check[i]=0;
    for(i=0;i<n;i++)
    {
        getchar(); //很重要,首先把读入N后的回车吸掉,然后吸收每行末尾的换行符
        scanf("%c %c",&l,&r);
        if(l!='-')
        {
            tree[i].left=l-'0';
            check[tree[i].left]=1;
        }
        else
            tree[i].left=-1;
        if(r!='-')
        {
            tree[i].right=r-'0';
            check[tree[i].right]=1;
        }
        else
            tree[i].right=-1;
        
    }
    for(i=0;i<n;i++)
    {
        if(check[i]==0)
        {
            root=i;
            break;
        }
    }
    
    return root;
}

//创建队列
Queue CreateQueue(){
    Queue q=(Queue)malloc(sizeof(struct queue));
    q->index=(int*)malloc(8*sizeof(int));
    q->front=q->rear=-1;
    return q;
}
bool isEmpty(Queue q)
{
    return(q->front==q->rear);
}
void add(Queue q,int x)
{
    if((q->rear+1)%10==q->front)
    {
        return;
    }
    else
    {
        q->rear=(q->rear+1)%8;
        q->index[q->rear]=x;
        
    }
}
int pop(Queue q){
    if(q->front==q->rear)
    {
        return -1;
    }
    else
    {
        q->front=(q->front+1)%8;
        return q->index[q->front];
    }
}
void traversal(int root2)
{
    int temp;//存放出队节点下标的临时变量
    Queue  q=CreateQueue();
    add(q,root2);
//    while(q->front!=q->rear)
    while(!isEmpty(q))
    {
        temp=pop(q);
        if(tree[temp].left!=-1&&tree[temp].right!=-1)
        {
            add(q,tree[temp].left);
            add(q,tree[temp].right);
        }
        else if(tree[temp].left!=-1&&tree[temp].right==-1)
            add(q,tree[temp].left);
        else if(tree[temp].left==-1&&tree[temp].right!=-1)
            add(q,tree[temp].right);
        else
        {
            printf("%d ",temp);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值