【PTA刷题整理】PAT 甲级 1004 Counting Leaves + 树的层序遍历

2020.02.29 终于到了周末了,能静下心来写一道甲级的题目辽


1004 Counting Leaves (30分)

A family hierarchy is usually presented by a pedigree tree. Your job is to count those family members who have no child.
Input Specification:

Each input file contains one test case. Each case starts with a line containing 0<N<100, the number of nodes in a tree, and M (<N), the number of non-leaf nodes. Then M lines follow, each in the format:

ID K ID[1] ID[2] … ID[K]

where ID is a two-digit number representing a given non-leaf node, K is the number of its children, followed by a sequence of two-digit ID’s of its children. For the sake of simplicity, let us fix the root ID to be 01.

The input ends with N being 0. That case must NOT be processed.
Output Specification:

For each test case, you are supposed to count those family members who have no child for every seniority level starting from the root. The numbers must be printed in a line, separated by a space, and there must be no extra space at the end of each line.

The sample case represents a tree with only 2 nodes, where 01 is the root and 02 is its only child. Hence on the root 01 level, there is 0 leaf node; and on the next level, there is 1 leaf node. Then we should output 0 1 in a line.
Sample Input:

2 1
01 1 02
Sample Output:

0 1


今天的题目是一道陈越姥姥出的题欸,第一眼看的时候还是因为英语不太过关看了很久啊😒
题目的意思是计算叶子节点的数量
输入:
给的输入N是树中节点的总个数,M是非叶子节点的个数,
然后就是输入M行数据,数据中包括每行的格式如下:

ID K ID[1] ID[2] …ID[K]

ID是一个两位数的数字(其实理解为一个数就行了),表示一个非叶结点。K表示其孩子的数量。随后是一个序列,序列中是该结点的孩子结点的两位数ID。根结点的ID固定为01。
拿样例来说说吧,树中有两个节点,一个非叶子节点
根节点01 有 1 个子节点 是02

输出:
需要我们输出从根结点开始的每一层中叶子节点的个数
样例中根节点01 只有 一个子节点 02 ,没有叶子节点 ,所以第一层是0
第二层02 , 没有子节点 ,他自己本身就是叶子节点 ,所以第二层是1


接下来就来说说思路
1.首先这不是我们常见的二叉树,而是一个M叉不规则树,首先要考虑的是存储方式,可以使用链表的方式,也可以用图的二维数组的存储方式
2.数组要开的足够大,以防出现N个节点,N层,除最后一层外每层存在一个子结点的情况
3.使用队列来进行层序遍历
4.这种做法降低了对于树存储上的需求,但是对于空间上实际上是有一点浪费的,也可以使用链表存储结合BFS来做

层序遍历

需要的用到的有一个队列、层记录layer、当前层的最后一个节点标记final,以及下一层的最后一个节点标记layerend
首先将根节点直接放入队列,当队列不为空时继续循环
创建标记index记录队首节点,然后将该节点出队列,通过当前所在数组的大小来判断是否有子节点,如果该节点没有子节点他自己本身就是叶子节点,当前层的子节点数量加一
若存在子节点,则将所有子节点放入队列中
当队首节点标记index等于当前层最后一个节点标记final时,这一层的便利结束,层记录数layer加一,并把当前层的最后一个节点final变更为下一层的最后一个节点标记layerend

	queue<int> search;
	//从根开始进行层序遍历,记录层和每层的最后一个,下一层的最后一个
	int layer = 0 , final = 1 , layerend; 
	search.push(1);
	while(!search.empty()){
		int index = search.front();
		search.pop();
		if(tree[index].size() == 0){
		//如果该节点没有子节点他自己本身就是叶子节点 
			ans[layer]++;
		}else{
			int temp;
			layerend = tree[index][tree[index].size() - 1]; 
			for(temp = 0;temp < tree[index].size() ; temp++){
				search.push(tree[index][temp]);
			}	
		}
		if(index == final){
			layer++;
			final = layerend;
		}
	}

最后根据所记录的层数layer并按格式将答案数组输出即可

#include<iostream>                  //输入输出流头文件
#include<stdio.h>                   //标准输入输出
#include<stdlib.h>
#include<math.h>                    //数学函数
#include<string.h>                  //C语言字符数组的字符串
#include<algorithm>                 //C++标准模板库的函数
#include<map>                       //map映射容器
#include<unordered_map>             //无序的map映射容器
#include<vector>                    //变长数组容器
#include<queue>                     //队列
#include<stack>                     //栈
#include<string>                    //C++string类
#include<set>                       //set集合
#define SIZE 100
using namespace std;                //标准命名空间

                                    //可以加入全局变量或者其他函数

int main(){                         //主函数
#ifdef ONLINE_JUDGE                 //如果有oj系统(在线判定),则忽略文件读入,否则使用文件作为标准输入
#else
    freopen("1.txt", "r", stdin);   //从1.txt输入数据
#endif
	int N , M;
	cin >> N >> M;
	//不规则树,用图的方式来表示,二维数组
	vector<int> tree[SIZE];
	//数组开到最大,以防出现N层,每层一个子节点的情况 
	int ans[SIZE];
	memset(ans , 0 , sizeof(ans));
	int id = 0 , k = 0;
	int child;
	for(int i = 0; i < M ; i++){
		cin >> id >> k;
		for(int j = 0 ; j < k;j++){
			cin >> child;
			tree[id].push_back(child);
		}
	}
	queue<int> search;
	//从根开始进行层序遍历,记录层和每层的最后一个,下一层的最后一个
	int layer = 0 , final = 1 , layerend; 
	search.push(1);
	while(!search.empty()){
		int index = search.front();
		search.pop();
		if(tree[index].size() == 0){//如果该节点没有子节点他自己本身就是叶子节点 
			ans[layer]++;
		}else{
			int temp;
			layerend = tree[index][tree[index].size() - 1]; 
			for(temp = 0;temp < tree[index].size() ; temp++){
				search.push(tree[index][temp]);
			}	
		}
		if(index == final){
			layer++;
			final = layerend;
		}
	}
    for(int i = 0 ; i < layer ; i++){
    	if(i != 0){
    		cout << " ";	
		}
		cout << ans[i];
	}
	cout << endl;
    return 0;                       
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值