7-1 列出叶结点(25 分) 【数据结构】

本文介绍了一种算法,用于输出给定二叉树的所有叶节点,采用从上到下、从左到右的顺序。通过寻找根节点并进行广度优先搜索,将叶节点编号存入向量中并最终输出。

7-1 列出叶结点(25 分)

对于给定的二叉树,本题要求你按从上到下、从左到右的顺序输出其所有叶节点。
输入格式:

首先第一行给出一个正整数 N(≤10),为树中结点总数。树中的结点从 0 到 N−1 编号。随后 N 行,每行给出一个对应结点左右孩子的编号。如果某个孩子不存在,则在对应位置给出 “-“。编号间以 1 个空格分隔。
输出格式:

在一行中按规定顺序输出叶节点的编号。编号间以 1 个空格分隔,行首尾不得有多余空格。
输入样例:

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

输出样例:

4 1 5

思路
先找出 根节点

怎么找呢
可以想到 根节点 不会是任何一个结点的 儿子
那么 我们只要标记一下 那些儿子 剩下的哪一个 就是 根节点

然后从根节点 往下遍历

遍历到 一个结点 没有儿子的 那么就将它 push 进一个 vector

然后最后 输出就可以了

AC代码

#include <cstdio>
#include <cstring>
#include <ctype.h>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <stack>
#include <set>
#include <numeric>
#include <sstream>
#include <iomanip>
#include <limits>

#define CLR(a) memset(a, 0, sizeof(a))
#define pb push_back

using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair<string, int> psi;
typedef pair<string, string> pss;

const double PI = 3.14159265358979323846264338327;
const double E = exp(1);
const double eps = 1e-30;

const int INF = 0x3f3f3f3f;
const int maxn = 1e2 + 5;
const int MOD = 1e9 + 7;

int v[10];

struct Node
{
    int l, r;
}q[10];

void init()
{
    CLR(q);
    CLR(v);
}

queue <int> Q;
vector <int> ans;

void bfs()
{
    int len = Q.size();
    for (int i = 0; i < len; i++)
    {
        int num = Q.front();
        Q.pop();
        if (q[num].l == -1 && q[num].r == -1)
            ans.pb(num);
        if (q[num].l != -1)
            Q.push(q[num].l);
        if (q[num].r != -1)
            Q.push(q[num].r);
    }
    if (Q.size())
        bfs();
}

int main()
{
    init();
    int n;
    scanf("%d", &n);
    char a, b;
    for (int i = 0; i < n; i++)
    {
        scanf(" %c %c", &a, &b);
        if (a == '-')
            q[i].l = -1;
        else
        {
            q[i].l = a - '0';
            v[a - '0'] = 1;
        }
        if (b == '-')
            q[i].r = -1;
        else
        {
            q[i].r = b - '0';
            v[b - '0'] = 1;
        }
    }
    int root;
    for (int i = 0; i < n; i++)
    {
        if (v[i] == 0)
        {
            root = i;
            break;
        }
    }
    Q.push(root);
    bfs();
    vector <int>::iterator it;
    for (it = ans.begin(); it != ans.end(); it++)
    {
        if (it != ans.begin())
            printf(" ");
        printf("%d", *it);
    }
    cout << endl;
}






<think>好的,用户的问题是如何按从上到下、从左到右的顺序输出二叉树的所有叶结点,并编程实现。我需要结合之前提供的引用内容,特别是关于二叉树的遍历方法,来设计解决方案。 首先,用户提到的引用1中有层次遍历的应用,引用2和3提到了先序、中序、后序遍历以及C++和Java的实现。层次遍历本身是按照从上到下、从左到右的顺序访问节点的,这正好符合用户的需求。因为层次遍历使用队列,逐层处理节点,可以确保叶节点按要求的顺序被访问到。 接下来,我需要考虑如何识别叶节点。叶节点的特点是左右子节点都为空。在遍历过程中,每访问一个节点,检查其左右子节点是否为空,如果是,则记录下来。 对于具体的实现步骤,层次遍历的算法通常是用队列实现的。首先将根节点入队,然后循环执行出队、检查子节点、子节点入队的操作。在这个过程中,每当遇到叶节点,就将其值添加到结果列表中。这样,最终得到的列表自然就是按层序排列的叶节点。 然后,需要针对不同的编程语言给出示例代码。用户提供的引用中有C++和Java的例子,所以应该用这两种语言来演示。比如在C++中,可以使用队列结构,循环处理每个节点。对于Java,同样使用队列,可能用LinkedList来实现。 还需要考虑特殊情况,比如空树的情况,这时候应该返回空列表或者不输出任何内容。另外,代码的结构要清晰,注释要说明关键步骤,方便用户理解。 最后,生成相关问题,可能涉及其他遍历方法的应用,或者叶节点其他操作,比如统计数量等,这些在引用中也有提到,可以作为相关问题提出。</think>### 二叉树层序输出叶结点解决方案 要按从上到下、从左到右顺序输出二叉树的所有叶结点,可采用层次遍历(广度优先搜索)算法。具体步骤如下: #### 1. 算法原理 层次遍历利用队列数据结构逐层访问结点,天然满足从上到下、从左到右的遍历顺序。当遍历过程中发现某结点无左右子树时,即为叶结点。 #### 2. 实现步骤 - 创建空队列,根结点入队 - 循环执行直到队列为空: 1. 出队一个结点 2. 若该结点是叶结点(左右子结点均为空),记录结点值 3. 将该结点的非空子结点依次入队 #### 3. 代码实现(C++) ```cpp void printLeavesLevelOrder(BiTree T) { if(!T) return; queue<BiTree> q; q.push(T); while(!q.empty()) { BiTree cur = q.front(); q.pop(); // 判断叶结点条件 if(!cur->lchild && !cur->rchild) { cout << cur->data << " "; } if(cur->lchild) q.push(cur->lchild); if(cur->rchild) q.push(cur->rchild); } } ``` #### 4. 代码实现(Java) ```java public void printLeavesLevelOrder(Node root) { if(root == null) return; Queue<Node> queue = new LinkedList<>(); queue.add(root); while(!queue.isEmpty()) { Node current = queue.poll(); if(current.left == null && current.right == null) { System.out.print(current.data + " "); } if(current.left != null) queue.add(current.left); if(current.right != null) queue.add(current.right); } } ``` #### 5. 算法- 时间复杂度:$O(n)$,每个结点访问一次 - 空间复杂度:$O(n)$,最坏情况存储所有结点 - 适用性:适用于需要按树层级关系处理结点的场景[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值