news 2026/6/10 19:08:54

Java 实现二叉搜索树:遍历、查询、构建

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 实现二叉搜索树:遍历、查询、构建
前言

二叉搜索树(Binary Search Tree,BST)是数据结构中最基础且应用广泛的树形结构,其核心特性是「左子树所有节点值 < 根节点值 < 右子树所有节点值」,基于这一特性可实现高效的查找、插入和遍历操作。本文将从底层原理出发,完整实现二叉搜索树的构建、前序 / 中序 / 后序 / 层次遍历、节点查询,并通过实战案例验证功能,帮助初学者彻底掌握 BST 的核心逻辑。

一、二叉搜索树核心概念
  1. 定义:二叉搜索树是一种二叉树,满足以下特性:
    • 任意节点的左子树中,所有节点值均小于该节点值;
    • 任意节点的右子树中,所有节点值均大于该节点值;
    • 左右子树也必须是二叉搜索树。
  2. 优势:基于有序特性,BST 的查找、插入操作时间复杂度平均为 O (logn)(平衡时),远优于线性结构。
二、完整代码实现
2.1 二叉树节点类(TreeNode)

首先定义二叉树节点结构,包含数据域、左孩子、右孩子指针:

package com.qcby; /** * 二叉树节点类 * 包含左孩子、右孩子、数据域 */ public class TreeNode { // 左孩子节点 public TreeNode lChild; // 右孩子节点 public TreeNode rChild; // 节点数据(Integer类型支持空值) public Integer data; /** * 构造方法:初始化节点数据 * @param data 节点存储的数值 */ public TreeNode(Integer data) { this.data = data; } }
2.2 二叉搜索树核心类(BinaryTree)

实现 BST 的构建、四种遍历方式、节点查询核心功能:

package com.qcby; import java.util.LinkedList; /** * 二叉搜索树核心类 * 包含:创建节点、前序遍历、中序遍历、后序遍历、层次遍历、节点查询 */ public class BinaryTree { // 根节点(头指针) TreeNode root; /** * 插入节点构建二叉搜索树 * 核心逻辑:根据BST特性,小于当前节点则往左子树插,大于则往右子树插 * @param value 待插入的节点值 */ public void create(Integer value) { // 1. 创建新节点 TreeNode newNode = new TreeNode(value); // 2. 若根节点为空,新节点直接作为根节点 if (root == null) { root = newNode; return; } // 3. 从根节点开始遍历,寻找插入位置 TreeNode curNode = root; while (true) { // 3.1 新节点值大于当前节点 → 往右子树走 if (curNode.data < newNode.data) { // 右孩子为空,直接插入 if (curNode.rChild == null) { curNode.rChild = newNode; return; } // 右孩子非空,继续遍历右子树 curNode = curNode.rChild; } else { // 3.2 新节点值小于等于当前节点 → 往左子树走 if (curNode.lChild == null) { curNode.lChild = newNode; return; } // 左孩子非空,继续遍历左子树 curNode = curNode.lChild; } } } /** * 前序遍历(根 → 左 → 右) * 递归实现:先访问根节点,再递归左子树,最后递归右子树 * @param root 当前遍历的根节点 */ void beforeOrder(TreeNode root) { // 递归终止条件:节点为空 if (root == null) { return; } // 1. 访问根节点 System.out.print(root.data + " "); // 2. 递归遍历左子树 beforeOrder(root.lChild); // 3. 递归遍历右子树 beforeOrder(root.rChild); } /** * 中序遍历(左 → 根 → 右) * 递归实现:先递归左子树,再访问根节点,最后递归右子树 * 注:BST的中序遍历结果为有序序列(升序) * @param root 当前遍历的根节点 */ void inOrder(TreeNode root) { if (root == null) { return; } // 1. 递归遍历左子树 inOrder(root.lChild); // 2. 访问根节点 System.out.print(root.data + " "); // 3. 递归遍历右子树 inOrder(root.rChild); } /** * 后序遍历(左 → 右 → 根) * 递归实现:先递归左子树,再递归右子树,最后访问根节点 * @param root 当前遍历的根节点 */ void afterOrder(TreeNode root) { if (root == null) { return; } // 1. 递归遍历左子树 afterOrder(root.lChild); // 2. 递归遍历右子树 afterOrder(root.rChild); // 3. 访问根节点 System.out.print(root.data + " "); } /** * 查找指定值的节点 * 基于BST特性:大于当前节点查右子树,小于查左子树,等于则返回 * @param root 遍历的根节点 * @param target 待查找的目标值 * @return 找到的节点(未找到返回null) */ public TreeNode searchNode(TreeNode root, Integer target) { // 递归终止条件:节点为空 或 找到目标节点 if (root == null || root.data.equals(target)) { return root; } // 目标值大于当前节点 → 查右子树 if (target > root.data) { return searchNode(root.rChild, target); } else { // 目标值小于当前节点 → 查左子树 return searchNode(root.lChild, target); } } /** * 层次遍历(广度优先遍历) * 基于队列实现:先入队根节点,出队时访问节点,再入队左右孩子 * @param root 遍历的根节点 */ void levelOrder(TreeNode root) { // 1. 空树直接返回 if (root == null) { return; } // 2. 创建队列存储节点(LinkedList实现Deque接口) LinkedList<TreeNode> queue = new LinkedList<>(); // 3. 根节点入队 queue.add(root); // 4. 队列非空时循环 while (!queue.isEmpty()) { // 4.1 出队并访问节点 TreeNode node = queue.pop(); System.out.print(node.data + " "); // 4.2 左孩子非空则入队 if (node.lChild != null) { queue.add(node.lChild); } // 4.3 右孩子非空则入队 if (node.rChild != null) { queue.add(node.rChild); } } } }
2.3 测试类(Test)

编写测试代码验证 BST 的构建、遍历、查询功能:

package com.qcby; /** * 测试类:验证二叉搜索树的构建、遍历、查询功能 */ public class Test { public static void main(String[] args) { // 1. 创建二叉搜索树实例 BinaryTree bt = new BinaryTree(); // 2. 插入节点构建树:5(根) → 3 → 7 → 0 → 4 → 6 → 9 bt.create(5); bt.create(3); bt.create(7); bt.create(0); bt.create(4); bt.create(6); bt.create(9); // 3. 测试层次遍历(预期输出:5 3 7 0 4 6 9) System.out.println("层次遍历结果:"); bt.levelOrder(bt.root); // 4. 测试前序遍历(预期输出:5 3 0 4 7 6 9) System.out.println("\n前序遍历结果:"); bt.beforeOrder(bt.root); // 5. 测试中序遍历(预期输出:0 3 4 5 6 7 9 → 升序) System.out.println("\n中序遍历结果:"); bt.inOrder(bt.root); // 6. 测试后序遍历(预期输出:0 4 3 6 9 7 5) System.out.println("\n后序遍历结果:"); bt.afterOrder(bt.root); // 7. 测试节点查询(查找值为5的节点) TreeNode targetNode = bt.searchNode(bt.root, 5); System.out.println("\n查找目标节点值:" + targetNode.data); } }
三、核心功能详解
3.1 构建二叉搜索树(create 方法)
  • 逻辑:从根节点开始,比较待插入值与当前节点值:
    • 若当前节点为空,直接插入;
    • 若待插入值更大,遍历右子树;
    • 若更小,遍历左子树;
    • 找到空的左 / 右孩子位置,完成插入。
  • 示例构建的树结构
3.2 四种遍历方式对比

3.3 节点查询(searchNode 方法)
  • 核心:利用 BST 有序特性,减少无效遍历:
    • 目标值 > 当前节点 → 查右子树;
    • 目标值 < 当前节点 → 查左子树;
    • 相等则返回当前节点;
    • 节点为空则返回 null(未找到)。
  • 时间复杂度:平衡树为 O (logn),最坏(退化为链表)为 O (n)。
四、运行结果

执行 Test 类,控制台输出如下:

六、总结

本文完整实现了二叉搜索树的构建、四种遍历方式和节点查询功能,核心要点:

  1. BST 的核心特性是「左小右大」,决定了插入和查询的逻辑;
  2. 中序遍历是 BST 的标志性遍历方式,结果为升序序列;
  3. 层次遍历依赖队列实现,是广度优先搜索的典型应用;
  4. 递归遍历的关键是「终止条件(节点为空)」和「遍历顺序」。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 3:18:08

Flutter 跨平台开发深度指南:从入门到原理全解析

一、引言 随着移动应用开发需求的增加&#xff0c;跨平台开发框架逐渐成为开发者的首选。Flutter 作为 Google 推出的跨平台开发框架&#xff0c;凭借其出色的性能和开发体验&#xff0c;吸引了大量开发者的关注。对于有一定 JavaScript 或前端开发经验的开发者来说&#xff0c…

作者头像 李华
网站建设 2026/6/10 13:21:07

硬盘突然坏掉,我花了半个月才把数据救回来…(附数据恢复工具)

为平时很多工作资料都在这块盘里&#xff0c;数据恢复的过程持续了小半个月&#xff0c;堪称一场心理和体力的双重折磨。好在最后&#xff0c;大部分文件都救回来了。虽然过程非常花时间&#xff0c;但至少没有全军覆没。&#x1f923;这次经历也算是给我自己上了一课&#xff…

作者头像 李华
网站建设 2026/6/10 17:50:08

树莓派运行 DeepSeek 大模型实战:轻量化模型选型与内存占用控制精要

树莓派运行 DeepSeek 大模型实战&#xff1a;轻量化模型选型与内存占用控制精要引言树莓派&#xff08;Raspberry Pi&#xff09;以其低廉的价格、强大的社区支持和丰富的扩展性&#xff0c;成为了嵌入式开发、教育、物联网和边缘计算的热门平台。随着人工智能&#xff08;AI&a…

作者头像 李华
网站建设 2026/6/9 19:27:51

Flutter UI 性能优化实践

. 布局优化核心目标是减少布局计算量&#xff0c;避免布局重排&#xff08;Relayout&#xff09;&#xff0c;提升布局效率。1. 懒加载减少布局计算‌作用阶段&#xff1a;布局阶段。优化逻辑&#xff1a;通过 Sliver 架构按需渲染可见区域子项&#xff0c;避免一次性计算所有子…

作者头像 李华
网站建设 2026/6/10 13:43:09

外网访问开源语音克隆工具 GPT-SoVITS

GPT-SoVITS 是一款开源的跨语言语音合成工具&#xff0c;结合了 GPT 和 SoVITS 的合成技术&#xff0c;在少量样本条件下实现语音克隆与合成。具有多种功能&#xff1a;极简样本需求、跨语言支持、全流程语音处理工具链等。应用在影视配音、有声内容创作、教育等多个领域。本文…

作者头像 李华
网站建设 2026/6/10 10:46:53

c#造个轮子-取色器TakeColor(附源码)

缘由看过上篇文章《OpenCvSharp基于颜色反差规避FBA面单贴标&#xff08;2&#xff09;》的都应该有印象这么一行代码&#xff1a;// 面单颜色列表&#xff08;十六进制格式&#xff09; privatestaticreadonly List<string> LabelColors new List<string> { …

作者头像 李华