1004 Counting Leaves【PAT (Advanced Level) Practice】

1004 Counting Leaves【PAT (Advanced Level) Practice】

Original question link:Preview question details - 1004 Counting Leaves (pintia.cn)

1.Original text of the title

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 0<N<100 0<N<100, the number of nodes in a tree, and M M M ( < N <N <N), the number of non-leaf nodes. Then M M 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 N 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

2. Title translation

The family hierarchy is usually represented by a family tree. Your task is to count the number of family members who have no children.

Input specifications:

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

ID K ID[1] ID[2] ... ID[K]

whereID is the two-digit number representing a given non-leaf node, K is the number of its child nodes, followed by the two numbers of its child nodes. A sequence of digitsID. For simplicity, we fix the ID of the root node to 01.

From import N N N ends with 0. This situation must not be handled. (Just don’t think about it N N N 0 0 The case of 0 was also mentioned earlier 0 < N < 100 0<N<100 0<N<100

Output specification:

For each test case, you should count those family members who have no children at each generational level, starting from the root. Numbers must be printed as one line, separated by spaces, with no extra spaces at the end of each line.

The example case represents a tree with only 2 nodes, where 01 is the root and 02 is its only child node. Therefore, on the root 01 level, there are 0 leaf nodes; on the next level, there are 1 leaf nodes. Then we should output the 0 1 line.

Example input:

2 1
01 1 02

Example output:

0 1

3. Problem-solving ideas

3.1 Question analysis

By entering a description of the family tree structure, count the number of family members without children at each generation level.

enter:

树中节点的数量N	非叶节点的数量M
M行输入:给定非叶节点的两位数字ID(根节点ID固定为 01)		其子节点的数量k	其子节点的两位数字 ID 的序列

Output:

顺次从根节点开始输出每一层没有子节点的结点个数

3.2 Basic ideas

By constructing a family tree and depth-first search, count the number of family members without children at each generation level, and output the results in hierarchical order.

3.3 Detailed steps

  1. Tree node structure definition:
    • TreeNodeThe structure contains three member variables, namely Child (pointer to child node), name (node ​​name, that is, a two-digit ID), Sibling (pointer to sibling node).
  2. Global variable definition:
    • Tree T[100]: Array used to store tree nodes, the index represents the node's ID.
    • int cnt[99]: Used to store the number of family members without children at each generation level.
    • int level, maxlevel: Used to track the hierarchical depth when recursively accessing tree nodes.
  3. Create new tree node function:
    • new_nodeThe function is used to create a new tree node, allocate memory and initialize the node's Child and Sibling pointers to NULL.
  4. Depth-first search access tree node function:
    • VisitThe function is used to recursively access tree nodes and count the number of family members without children at each generation level.
    • If the node has no children, increase the number of family members at the corresponding level; otherwise, recursively visit the child nodes and then visit the sibling nodes.
  5. Main function:
    • Initialize the tree node array and count array.
    • Read the input and build the tree structure.
      • The input starts with N and M, which represent the number of nodes and the number of non-leaf nodes respectively.
      • The subsequent input is the information of non-leaf nodes, including nodeID, the number of child nodes and the ID of child nodes.
    • Call the Visit function to calculate the number of family members without children at each generation level.
    • Output results: Output the number of family members without children at each generation level, in hierarchical order, separated by spaces.

3.4 Points to note

4. Reference answer

#include <stdio.h>
#include <malloc.h>

// 定义树节点的结构体
typedef struct TreeNode *Tree;
struct TreeNode {
    
    
    Tree Child;      // 子节点
    int name;        // 节点名称
    Tree Sibling;    // 兄弟节点
};

Tree T[100];          // 存储树节点的数组
int cnt[99], level, maxlevel;  // cnt数组用于存储每个辈分层次上没有子女的家庭成员数量,level和maxlevel用于追踪层次深度

// 创建新的树节点
Tree new_node() {
    
    
    Tree temp;
    temp = (Tree)malloc(sizeof(struct TreeNode));
    temp->Child = temp->Sibling = NULL;
    return temp;
}

// 深度优先搜索访问树节点
void Visit(Tree T) {
    
    
    if (!T->Child)
        cnt[level]++;  // 如果节点没有子女,增加相应辈分的家庭成员数量
    else {
    
    
        level++;  // 进入下一层次
        if (level > maxlevel)
            maxlevel = level;  // 更新最大层次深度
        Visit(T->Child);  // 递归访问子节点
        level--;  // 返回上一层次
    }
    if (T->Sibling)
        Visit(T->Sibling);  // 递归访问兄弟节点
}

int main() {
    
    
    int i, j, N, M;
    int id1, id2, k;

    // 初始化树节点数组和计数数组
    for (i = 0; i < 99; i++) {
    
    
        T[i + 1] = NULL;
        cnt[i] = 0;
    }

    level = maxlevel = 0;
    scanf("%d %d", &N, &M);

    // 读取输入,构建树
    T[1] = new_node();
    T[1]->name = 1;
    // 读取输入,构建树结构
    for (i = 0; i < M; i++) {
    
    
        scanf("%d %d", &id1, &k);

        // 如果当前节点不存在,则创建新节点并初始化
        if (!T[id1]) {
    
    
            T[id1] = new_node();
            T[id1]->name = id1;
        }

        // 如果节点有子节点,读取第一个子节点的信息
        if (k) {
    
    
            scanf("%d", &id2);

            // 如果子节点不存在,则创建新节点并初始化
            if (!T[id2]) {
    
    
                T[id2] = new_node();
                T[id2]->name = id2;
            }

            T[id1]->Child = T[id2];  // 设置当前节点的子节点
            id1 = id2;  // 更新当前节点为子节点,用于处理兄弟节点
        }

        // 处理当前节点的兄弟节点
        for (j = 1; j < k; j++) {
    
    
            scanf("%d", &id2);

            // 如果兄弟节点不存在,则创建新节点并初始化
            if (!T[id2]) {
    
    
                T[id2] = new_node();
                T[id2]->name = id2;
            }

            T[id1]->Sibling = T[id2];  // 设置当前节点的兄弟节点
            id1 = id2;  // 更新当前节点为兄弟节点,用于处理下一个兄弟节点
        }
    }

    // 计算每个辈分层次上没有子女的家庭成员数量
    Visit(T[1]);

    // 输出结果
    printf("%d", cnt[0]);
    for (i = 1; i <= maxlevel; i++)
        printf(" %d", cnt[i]);
    printf("\n");

    // 释放内存
    for (i = 0; i < 99; i++) {
    
    
        free(T[i + 1]);
        T[i + 1] = NULL;
        cnt[i] = 0;
    }

    return 0;
}

5.Knowledge expansion

Depth-First Search (DFS)

Depth-First Search (DFS) is a search algorithm for data structures such as graphs and trees. The algorithm starts from the starting node, visits every possible branch as deep as possible until it can no longer continue, and then backtracks to the previous node to continue trying other branches. DFS is usually implemented using recursion or stack.

Here are the basic steps for depth-first search:

  1. Visit the starting node: Mark the starting node as visited and add it to the access path.

  2. Recursion or stack: Repeat the above steps for each unvisited neighbor of the starting node. You can use recursive calls or use the stack to track the order in which nodes are accessed.

  3. Backtracking: When you can no longer go deeper, backtrack to the previous node and continue trying other branches.

  4. Repeat: Repeat steps 2 and 3 until all reachable nodes have been visited.

Depth-first search is widely used in solving maze problems, graph traversal, topological sorting and other problems.

Guess you like

Origin blog.csdn.net/weixin_40171190/article/details/134746759