news 2026/4/2 10:33:01

二叉树的相关知识以及代码实现(Java)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
二叉树的相关知识以及代码实现(Java)

一、二叉树的定义与基本概念

二叉树是一种非线性数据结构,每个节点最多包含 2 个子节点(左子节点、右子节点),核心特点:

(1)每个节点的子树数量不超过 2;

(2)左、右子树是有序的(即使只有一个子树,也需明确是左 / 右子树);

(3)可衍生出多种特殊结构(如二叉搜索树、完全二叉树、满二叉树等)。

二、创建二叉树的常见方法

1. 节点类定义

二叉树的基础是 “节点”,需包含数据域指针域(指向左 / 右子节点),Java 实现示例:

package com.heima.Tree; public class TreeNode { // 左子节点指针 public TreeNode lChild; // 右子节点指针 public TreeNode rChild; // 数据域(存储节点值) public Integer data; // 构造方法:初始化节点数据 public TreeNode(Integer data) { this.data = data; } }

2. 手动创建二叉树(以 “二叉搜索树” 为例)

通过create方法插入节点,遵循二叉搜索树规则(左子树值 < 父节点值 < 右子树值),实现逻辑(1)若树为空,新节点作为根节点;

(2)若树非空,从根节点开始比较:

1)新节点值 > 当前节点值 → 走右子树(直到右子树为空,插入新节点);

2)新节点值 < 当前节点值 → 走左子树(直到左子树为空,插入新节点)。

Java 实现示例:

public class BinaryTree { // 树的根节点指针 private TreeNode root; // 插入节点的方法 public void create(Integer value) { // 新建节点 TreeNode newNode = new TreeNode(value); // 情况1:树为空 → 新节点作为根 if (root == null) { root = newNode; return; } // 情况2:树非空 → 从根开始遍历插入 TreeNode curNode = root; while (true) { // 新节点值 > 当前节点值 → 走右子树 if (curNode.data < newNode.data) { // 右子树为空 → 插入新节点 if (curNode.rChild == null) { curNode.rChild = newNode; return; } // 右子树非空 → 继续遍历右子树 curNode = curNode.rChild; } // 新节点值 < 当前节点值 → 走左子树 else { // 左子树为空 → 插入新节点 if (curNode.lChild == null) { curNode.lChild = newNode; return; } // 左子树非空 → 继续遍历左子树 curNode = curNode.lChild; } } } }

3. 调用方法构建二叉树

创建BinaryTree对象,多次调用create方法插入节点,即可构建二叉树。示例(插入值5、3、7、8、4、6、9):

public static void main(String[] args) { BinaryTree bt = new BinaryTree(); bt.create(5); // 根节点 bt.create(3); // 5的左子节点 bt.create(7); // 5的右子节点 bt.create(8); // 7的右子节点 bt.create(4); // 3的右子节点 bt.create(6); // 7的左子节点 bt.create(9); // 8的右子节点 }

最终构建的二叉搜索树结构:

5 / \ 3 7 \ / \ 4 6 8 \ 9

三、二叉树的应用场景

二叉树(含其特殊结构)在多领域有核心作用:

(1)表达式树:表示数学表达式(如a*(b+c),根节点为*,左子树为a,右子树为(b+c));

(2)二叉搜索树:实现高效的 “增删查”(平均时间复杂度 O (logn));

(3)堆结构:实现优先队列(大顶堆 / 小顶堆),用于任务调度、TopK 问题等;

(4)哈夫曼编码树:数据压缩(如 ZIP 压缩),通过字符出现频率构建树,生成最短编码;(5)决策树:机器学习中用于分类 / 回归(如 ID3、C4.5、CART 树);

(6)平衡二叉树(如 AVL 树、红黑树):解决普通二叉搜索树的 “退化成链表” 问题,用于 JDK 集合(如TreeMap)。

四、创建二叉树的注意事项

(1)避免循环引用(如节点的左 / 右子节点指向自身或祖先节点);

(2)递归创建大二叉树时,注意栈溢出风险(可改用迭代方式);

(3)空节点的表示需统一(用null),避免逻辑混乱;

(4)不同的 “插入 / 遍历顺序” 会生成不同结构的二叉树(如同一组值,按不同顺序插入,二叉搜索树的形态会不同)。

五、二叉树的 4 种遍历方式

遍历的核心是 “按规则访问树中所有节点,且每个节点仅访问一次”。不同的遍历顺序对应不同的应用场景,我们逐一解析。

1. 先序遍历(Preorder Traversal)

(1)概念与规则

先序遍历的顺序是:根节点 → 左子树 → 右子树。优先访问当前节点,再递归处理左右子树。

(2)遍历步骤

1)访问当前根节点(如打印节点值);

2)递归遍历左子树;

3)递归遍历右子树。

(3)示例

以下二叉树的先序遍历结果为:A → B → D → E → C → F

A / \ B C / \ \ D E F
// 先序遍历(递归) public void preOrder(TreeNode root) { if (root == null) { return; } // 1. 访问根节点 System.out.println(root.data); // 2. 递归左子树 preOrder(root.lChild); // 3. 递归右子树 preOrder(root.rChild); }
(4)应用场景

1)目录结构打印(先输出当前目录,再遍历子目录);

2)表达式树生成前缀表达式(如+ A * B C);

3)树的序列化(保存树结构以便重建)。

(5)复杂度

1)时间复杂度:O(n)(每个节点访问一次);

2)空间复杂度:递归方式为O(h)(h 为树高),非递归方式最坏为O(n)

2. 中序遍历(In-order Traversal)

(1)概念与规则

中序遍历的顺序是:左子树 → 根节点 → 右子树。对于二叉搜索树(BST),中序遍历会得到升序的节点序列,这是其最核心的特性。

(2)示例

以下二叉树的中序遍历结果为:4 → 2 → 5 → 1 → 3

1 / \ 2 3 / \ 4 5
// 中序遍历(递归) public void inOrder(TreeNode root) { if (root == null) { return; } // 1. 递归左子树 inOrder(root.lChild); // 2. 访问根节点 System.out.println(root.data); // 3. 递归右子树 inOrder(root.rChild); }
(3)应用场景

1)二叉搜索树的升序遍历;

2)表达式树生成中缀表达式(如4 + 2 * 5);

3)编译原理中的语法树遍历。

3. 后序遍历(Postorder Traversal)

(1)概念与规则

后序遍历的顺序是:左子树 → 右子树 → 根节点。特点是 “最后访问根节点”,常用于 “先处理子节点,再处理父节点” 的场景。

(2)示例

以下二叉树的后序遍历结果为:D → E → B → F → C → A

A / \ B C / \ \ D E F
// 后序遍历(递归) public void postOrder(TreeNode root) { if (root == null) { return; } // 1. 递归左子树 postOrder(root.lChild); // 2. 递归右子树 postOrder(root.rChild); // 3. 访问根节点 System.out.println(root.data); }
(3)应用场景

1)表达式树计算结果(如(3+4)*5);

2)文件系统删除(先删子目录 / 文件,再删父目录);

3)内存释放(先释放子节点,再释放父节点)。

4. 层次遍历(Level Order Traversal)

(1)概念与规则

层次遍历也叫广度优先遍历(BFS),按 “层级顺序” 访问节点:从根节点开始,依次访问第 1 层、第 2 层…… 同一层从左到右访问。

实现依赖队列:先入队根节点,出队时访问该节点,并将其左右子节点入队,循环直到队列为空。

(2)示例:Java 实现(队列)
// 层次遍历(基于队列) 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.println(node.data); // 左子节点入队 if (node.lChild != null) { queue.offer(node.lChild); } // 右子节点入队 if (node.rChild != null) { queue.offer(node.rChild); } } }
(3)应用场景

1)求二叉树的最小深度;

2)展示家族 / 组织的层级关系;

3)网络爬虫按链接层级抓取网页。

六、二叉搜索树的节点查询

对于二叉搜索树(BST),节点查询可以利用其 “左子树值 < 根节点值 < 右子树值” 的特性,实现高效查找(平均时间复杂度O(logn))。

(1)查询逻辑

1)若当前节点为空,返回null(未找到);

2)若当前节点值等于目标值,返回该节点;

3)若当前节点值 < 目标值,递归查询右子树;

4)若当前节点值 > 目标值,递归查询左子树。

(2)代码Java 实现

// 二叉搜索树节点查询 public TreeNode findNode(TreeNode root, Integer target) { // 树为空,未找到 if (root == null) { return null; } // 找到目标节点 if (root.data.equals(target)) { return root; } // 目标值更大,查右子树 else if (root.data < target) { return findNode(root.rChild, target); } // 目标值更小,查左子树 else { return findNode(root.lChild, target); } }

七、总结

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/29 8:22:22

pandas基础操作

文章目录 1. Series 与 DataFrame2. 数据查看与基本信息获取3. 数据选择与筛选4. 数据清洗与预处理5. 数据排序与重置索引6. 数据分组与聚合分析7. 数据合并 1. Series 与 DataFrame Series&#xff1a;一维带标签数组&#xff0c;类似于 Excel 中的单列数据 import pandas a…

作者头像 李华
网站建设 2026/3/26 19:27:49

泳池智能水管家推荐:5款高性价比设备实测解析

泳池智能水管家推荐&#xff1a;5款高性价比设备实测解析在洗浴行业竞争日益激烈的今天&#xff0c;水质管理正成为决定用户复购率的核心因素。当浴室能够实现“无呛鼻氯味、水体清澈透亮、皮肤泡后不痒、空气清新舒适”的体验时&#xff0c;其竞争力便已悄然超越传统服务模式。…

作者头像 李华
网站建设 2026/4/1 18:28:06

2025OpenTiny星光ShowTime!年度贡献者征集启动!

前言 携手共创&#xff0c;致敬不凡&#xff01; 2025年&#xff0c;OpenTiny持续在前端开源领域扎根&#xff0c;每一位开发者都是推动项目共同前行的宝贵力量。从bug修复&#xff0c;到技术探讨&#xff1b;从参与开源活动&#xff0c;到输出技术文章&#xff1b;从使用项目…

作者头像 李华
网站建设 2026/4/1 15:07:30

工业控制系统测试:从功能验证到安全防御的范式重构

1. 工业控制系统测试的时代演进 随着工业4.0和智能制造的深入推进&#xff0c;工业控制系统&#xff08;ICS&#xff09;已从封闭的物理控制单元&#xff0c;演变为集成了IT、OT和IoT的复杂信息物理系统。截至2025年&#xff0c;全球超过60%的制造企业完成了生产系统的网络化改…

作者头像 李华