二叉树算法之二叉树遍历(前序、中序、后序、层次遍历)

news/2024/10/21 20:32:02/

二叉树遍历是指按照某种顺序访问二叉树的所有节点。常见的二叉树遍历方式包括前序遍历(Preorder Traversal)、中序遍历(Inorder Traversal)、后序遍历(Postorder Traversal)和层次遍历(Level-order Traversal)。不同的遍历方式有不同的应用场景,下面我们详细介绍这几种遍历方式及其实现。

1. 前序遍历(Preorder Traversal)

在前序遍历中,按照“根节点 -> 左子树 -> 右子树”的顺序遍历二叉树的节点。即:首先访问根节点,然后递归地遍历左子树,最后递归地遍历右子树。

前序遍历的顺序:
当前节点 -> 左子节点 -> 右子节点

前序遍历的递归实现:

// 定义二叉树节点
class TreeNode {int val;TreeNode left, right;TreeNode(int val) {this.val = val;this.left = this.right = null;}
}public class BinaryTreeTraversal {// 前序遍历 - 递归实现public void preorder(TreeNode root) {if (root == null) {return;}System.out.print(root.val + " ");  // 访问根节点preorder(root.left);  // 递归遍历左子树preorder(root.right);  // 递归遍历右子树}
}
前序遍历的非递归实现:

可以用栈模拟递归的过程,先访问根节点,然后将右子树和左子树依次压栈,确保左子树先被遍历。

import java.util.Stack;public class BinaryTreeTraversal {// 前序遍历 - 非递归实现public void preorderIterative(TreeNode root) {if (root == null) {return;}Stack<TreeNode> stack = new Stack<>();stack.push(root);while (!stack.isEmpty()) {TreeNode node = stack.pop();System.out.print(node.val + " ");  // 访问根节点if (node.right != null) {stack.push(node.right);  // 右子树入栈}if (node.left != null) {stack.push(node.left);  // 左子树入栈}}}
}

2. 中序遍历(Inorder Traversal)

在中序遍历中,按照“左子树 -> 根节点 -> 右子树”的顺序遍历二叉树的节点。即:首先递归地遍历左子树,然后访问根节点,最后递归地遍历右子树。

中序遍历的顺序:
左子节点 -> 当前节点 -> 右子节点

中序遍历的递归实现:

public class BinaryTreeTraversal {// 中序遍历 - 递归实现public void inorder(TreeNode root) {if (root == null) {return;}inorder(root.left);  // 递归遍历左子树System.out.print(root.val + " ");  // 访问根节点inorder(root.right);  // 递归遍历右子树}
}
中序遍历的非递归实现:

同样可以使用栈来实现,先遍历到最左边的节点,然后逐步回溯访问根节点,最后遍历右子树。

import java.util.Stack;public class BinaryTreeTraversal {// 中序遍历 - 非递归实现public void inorderIterative(TreeNode root) {Stack<TreeNode> stack = new Stack<>();TreeNode curr = root;while (curr != null || !stack.isEmpty()) {while (curr != null) {stack.push(curr);  // 左子树入栈curr = curr.left;}curr = stack.pop();  // 弹出栈顶节点并访问System.out.print(curr.val + " ");curr = curr.right;  // 遍历右子树}}
}

3. 后序遍历(Postorder Traversal)

在后序遍历中,按照“左子树 -> 右子树 -> 根节点”的顺序遍历二叉树的节点。即:首先递归地遍历左子树,然后递归地遍历右子树,最后访问根节点。

后序遍历的顺序:
左子节点 -> 右子节点 -> 当前节点

后序遍历的递归实现:

public class BinaryTreeTraversal {// 后序遍历 - 递归实现public void postorder(TreeNode root) {if (root == null) {return;}postorder(root.left);  // 递归遍历左子树postorder(root.right);  // 递归遍历右子树System.out.print(root.val + " ");  // 访问根节点}
}
后序遍历的非递归实现:

后序遍历较复杂,需要两个栈,一个用于模拟递归,另一个用于输出结果。

import java.util.Stack;public class BinaryTreeTraversal {// 后序遍历 - 非递归实现public void postorderIterative(TreeNode root) {if (root == null) {return;}Stack<TreeNode> stack = new Stack<>();Stack<TreeNode> output = new Stack<>();stack.push(root);while (!stack.isEmpty()) {TreeNode node = stack.pop();output.push(node);if (node.left != null) {stack.push(node.left);  // 左子树入栈}if (node.right != null) {stack.push(node.right);  // 右子树入栈}}while (!output.isEmpty()) {System.out.print(output.pop().val + " ");  // 输出结果}}
}

4. 层次遍历(Level-order Traversal)

层次遍历是按照每一层节点的顺序从上到下,从左到右依次遍历二叉树的节点。可以通过队列实现,每次从队列中取出一个节点,然后将其左右子节点依次加入队列。

层次遍历的顺序:
按照从上到下、从左到右的层次顺序遍历节点

层次遍历的实现:

import java.util.LinkedList;
import java.util.Queue;public class BinaryTreeTraversal {// 层次遍历 - 使用队列实现public void levelOrder(TreeNode root) {if (root == null) {return;}Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);while (!queue.isEmpty()) {TreeNode node = queue.poll();System.out.print(node.val + " ");  // 访问当前节点if (node.left != null) {queue.offer(node.left);  // 左子节点入队}if (node.right != null) {queue.offer(node.right);  // 右子节点入队}}}
}

四种遍历的总结

  • 前序遍历(Preorder Traversal):根 -> 左 -> 右,通常用于复制树。
  • 中序遍历(Inorder Traversal):左 -> 根 -> 右,通常用于输出升序排序(对二叉搜索树)。
  • 后序遍历(Postorder Traversal):左 -> 右 -> 根,通常用于删除树或者计算子树的大小。
  • 层次遍历(Level-order Traversal):按层次顺序遍历,常用于广度优先搜索。

这些遍历方式各有特点,应用于不同的场景。


http://www.ppmy.cn/news/1540891.html

相关文章

Vue前端预览docx文档

Vue前端预览docx文档 实现效果 vue代码 <el-dialog title"预览" :visible.sync"filePreview"><div ref"file"></div></el-dialog>引入依赖文件 官方文档地址 https://www.npmjs.com/package/docx-preview?activeTabre…

SpringCloud Gateway保姆级入门教程

什么是微服务网关 SpringCloud Gateway是Spring全家桶中一个比较新的项目&#xff0c;Spring社区是这么介绍它的&#xff1a; 该项目借助Spring WebFlux的能力&#xff0c;打造了一个API网关。旨在提供一种简单而有效的方法来作为API服务的路由&#xff0c;并为它们提供各种增强…

uniapp配置微信小程序分包(分包优化)

1.manifest.json中 源码视图中找到mp-weixin&#xff0c;新增代码"optimization":{"subPackages":true}&#xff0c;如下图所示 "optimization" : {"subPackages" : true } 2.pages.json中 分包内静态文件示例 "subPackages&…

利用mydumper从MySQL迁移数据到OceanBase数据库命令记录

一&#xff1a;中转服务器环境准备 1、下载安装包。 请根据需要在 下载安装包 中&#xff0c;下载对应的安装包并安装。 2、在数据库主机上解压缩安装包。 以 mydumper-0.12.7-2-zstd.el7.x86_64.rpm 为示例。 rpm2cpio mydumper-0.12.7-2-zstd.el7.x86_64.rpm | cpio -di…

Redis 一些问题

关闭Linux防火墙 找到redis 配置文件 注释 #bind 127.0.0.1 修改 protected-mode yes 改为no 如果报&#xff1a;NOAUTH Authentication required错误就是设置了密码 auth 你的密码 配置Redis spring.redis.host192.168.44.132 spring.redis.port6379 spring.redis.d…

如何从小白成长为大神

大学新生编程入门攻略&#xff1a;如何从小白成长为大神 编程已成为当代大学生的重要技能&#xff0c;但面对众多编程语言和学习资源&#xff0c;新生们常常感到迷茫。以下是大学新生入门编程的最佳路径&#xff0c;助你打下坚实的基础&#xff0c;推动未来职业发展。 方向一…

灵当CRM index.php 任意文件上传漏洞复现

0x01 产品描述&#xff1a; 灵当CRM是一款专为中小企业量身定制的智能客户关系管理工具&#xff0c;由上海灵当信息科技有限公司开发和运营。该系统广泛应用于多个行业&#xff0c;包括金融、教育、医疗、IT服务及房地产等领域&#xff0c;旨在满足企业对客户个性化管理的需求&…

除GOF23种设计模式之简单工厂模式

文章目录 1. 简介2. 代码2.1 抽象类&#xff1a;Course.java2.2 产品A:JavaCourse.java2.3 产品B:PythonCourse.java2.4 工厂:CourseFactory.java2.5 测试&#xff1a;Test.java 3. 心得参考链接&#xff08;无&#xff09; 1. 简介 简单工厂模式(Simple Factory Patern):又称…