多叉树的递归/层序遍历

简介: 多叉树是二叉树的扩展,每个节点可有多个子节点。遍历方式类似:递归实现DFS时无中序概念;层序遍历(BFS)用队列处理,支持记录深度与权重,代码结构清晰统一。

一句话总结
多叉树结构就是 二叉树结构 的延伸,二叉树是特殊的多叉树。森林是指多个多叉树的集合。
多叉树的遍历就是 二叉树遍历 的延伸。
二叉树的节点长这样,每个节点有两个子节点:
class TreeNode {
int val;
TreeNode left;
TreeNode right;
}
多叉树的节点长这样,每个节点有任意个子节点:
class Node {
int val;
List children;
}
就这点区别,其他没了。
递归遍历(DFS)
对比二叉树的遍历框架看多叉树的遍历框架吧:
// 二叉树的遍历框架
void traverse(TreeNode root) {
if (root == null) {
return;
}
// 前序位置
traverse(root.left);
// 中序位置
traverse(root.right);
// 后序位置
}

// N 叉树的遍历框架
void traverse(Node root) {
if (root == null) {
return;
}
// 前序位置
for (Node child : root.children) {
traverse(child);
}
// 后序位置
}
唯一的区别是,多叉树没有了中序位置,因为可能有多个节点嘛,所谓的中序位置也就没什么意义了。
层序遍历(BFS)
多叉树的层序遍历和 二叉树的层序遍历 一样,都是用队列来实现,无非就是把二叉树的左右子节点换成了多叉树的所有子节点。所以多叉树的层序遍历也有三种写法,下面一一列举。
写法一
第一种层序遍历写法:
void levelOrderTraverse(Node root) {
if (root == null) {
return;
}
Queue q = new LinkedList<>();
q.offer(root);
while (!q.isEmpty()) {
Node cur = q.poll();
// 访问 cur 节点
System.out.println(cur.val);

    // 把 cur 的所有子节点加入队列
    for (Node child : cur.children) {
        q.offer(child);
    }
}

}
写法二
第二种能够记录节点深度的层序遍历写法:
void levelOrderTraverse(Node root) {
if (root == null) {
return;
}
Queue q = new LinkedList<>();
q.offer(root);
// 记录当前遍历到的层数(根节点视为第 1 层)
int depth = 1;

while (!q.isEmpty()) {
    int sz = q.size();
    for (int i = 0; i < sz; i++) {
        Node cur = q.poll();
        // 访问 cur 节点,同时知道它所在的层数
        System.out.println("depth = " + depth + ", val = " + cur.val);

        for (Node child : cur.children) {
            q.offer(child);
        }
    }
    depth++;
}

}
写法三
第三种能够适配不同权重边的写法:
class State {
Node node;
int depth;

public State(Node node, int depth) {
    this.node = node;
    this.depth = depth;
}

}

void levelOrderTraverse(Node root) {
if (root == null) {
return;
}
Queue q = new LinkedList<>();
// 记录当前遍历到的层数(根节点视为第 1 层)
q.offer(new State(root, 1));

while (!q.isEmpty()) {
    State state = q.poll();
    Node cur = state.node;
    int depth = state.depth;
    // 访问 cur 节点,同时知道它所在的层数
    System.out.println("depth = " + depth + ", val = " + cur.val);

    for (Node child : cur.children) {
        q.offer(new State(child, depth + 1));
    }
}

}

相关文章
|
存储 SQL NoSQL
HarmonyOS学习路之开发篇—数据管理(分布式数据服务)
分布式数据服务(Distributed Data Service,DDS) 为应用程序提供不同设备间数据库数据分布式的能力。通过调用分布式数据接口,应用程序将数据保存到分布式数据库中。通过结合帐号、应用和数据库三元组,分布式数据服务对属于不同应用的数据进行隔离,保证不同应用之间的数据不能通过分布式数据服务互相访问。在通过可信认证的设备间,分布式数据服务支持应用数据相互同步,为用户提供在多种终端设备上最终一致的数据访问体验。
|
存储 网络协议 中间件
DDS数据分发服务
DDS数据分发服务
1840 0
|
存储 前端开发 安全
webhook是什么 与API的区别在哪里
webhooks是一个api概念,是微服务api的使用范式之一,也被成为反向api,即:前端不主动发送请求,完全由后端推送。 举个常用例子,比如你的好友发了一条朋友圈,后端将这条消息推送给所有其他好友的客户端,就是 Webhooks 的典型场景。
webhook是什么 与API的区别在哪里
|
Java p3c
sonar入门:使用阿里规范扫描代码质量
sonar入门:使用阿里规范扫描代码质量
2959 0
sonar入门:使用阿里规范扫描代码质量
|
关系型数据库 MySQL 数据安全/隐私保护
查看mysql 默认端口号和修改端口号
1. 登录mysql mysql -u root -p //输入密码    2. 使用命令show global variables like 'port';查看端口号 mysql> show global variables like 'port';    3. 修改端口,编辑/etc/my.cnf文件,早期版本有可能是my.conf文件名,增加端口参数,并且设定端口,注意该端口未被使用,保存退出。
24416 0
|
人工智能 安全 测试技术
本周 AI Benchmark 方向论文推荐
由北京大学和微软亚洲研究院的魏李等人提出的 FEA-Bench,是一个专为评估大型语言模型(LLMs)在代码库级别进行增量开发能力的基准测试。它从 83 个 GitHub 仓库中收集了 1,401 个任务实例,专注于新功能的实现。研究表明,即使是先进的 LLMs 在此任务中的表现仍远低于预期,揭示了仓库级代码开发的重大挑战。
819 0
|
人工智能 Java 程序员
一文彻底搞定C语言的表达式和语句
本文介绍了C语言中的表达式和语句,涵盖算术、关系等表达式及各类语句的用法,帮助初学者理解核心概念。本文介绍C语言表达式(算术、关系等)和语句(表达式、复合、控制、函数、空语句),助你掌握核心概念。
1047 0
一文彻底搞定C语言的表达式和语句
|
存储 开发工具 git
git工具使用教程全讲解
本文介绍了版本控制的概念及其重要性,详细对比了多种版本控制工具,如VSS、CVS、SVN和Git,重点讲解了Git的基本使用方法、工作原理及与SVN的区别。此外,文章还介绍了GitHub、GitLab和Gitee等流行的代码托管平台,以及如何在这些平台上注册账号、创建和管理仓库。最后,文章还提供了如何在IntelliJ IDEA中配置和使用Git的具体步骤。
696 1
|
NoSQL Redis 索引
RedisTemplate.opsForList()用法简介并举例
RedisTemplate.opsForList()用法简介并举例
3605 2
|
存储 IDE 搜索推荐
解锁Python黑科技:字典树Trie,让你的数据检索快到飞起!
字典树(Trie),又称前缀树或单词查找树,是一种专为字符串快速检索设计的高效数据结构。本文深入探讨了Trie树的基本原理及其在Python中的实现方法,并展示了如何通过插入和搜索操作来提高数据检索性能。Trie树广泛应用于自动补全、拼写检查、IP路由表以及数据压缩等领域,其高效的前缀匹配能力使其成为处理大量字符串的理想选择。通过本文的学习,你将能更好地利用Trie树解决实际问题,提升编程技能。
703 0