算法系列之数据结构-二叉树

_20250303234623.jpg

在计算机科学中,数据结构是组织和存储数据的方式,以便能够高效地访问和修改数据。树(Tree)是一种非常重要的非线性数据结构,广泛应用于各种算法和应用中。本文将详细介绍树的基本概念、常见类型以及用Java实现树的遍历。

树的基本概念

树是一种非线性数据结构,它由一组节点组成,每个节点最多只能有一个父节点,但可以有多个子节点。树的结构类似于自然界中的树,具有层次分明的特点。以下是数的一些基本术语:

  • 根节点(Root):树的顶端节点,没有父节点。

  • 子节点(Child):一个节点的直接下级节点。

  • 父节点(Parent):一个节点的直接上级节点。

  • 叶子节点(Leaf):没有子节点的节点。

  • 深度(Depth):从根节点到某个节点的路径长度。

  • 高度(Height):从某个节点到叶子节点的最长路径长度。

_20250303212232.jpg

树的常见类型

  1. 二叉树(Binary Tree)

二叉树是一种特殊的树,每个节点最多有两个子节点,通常称为左子节点和右子节点。二叉树具有以下性质:

  • 第i层的最大节点数为 2 i − 1 2^{i-1} 2i1

  • 高度为k的二叉树最多有 2 k − 1 2^k - 1 2k1个节点。

  1. 满二叉树(Full Binary Tree)

满二叉树是指高度为k的二叉树并且有 2 k − 1 2^k - 1 2k1个节点的二叉树。及每层的节点数都是满的。

  1. 完全二叉树(Complete Binary Tree)

完全二叉树也是一种特殊的二叉树,除了最后一层,其他层都满,且最后一层节点从左到右排列。可见,满二叉树必为完全二叉树,但完全二叉树不一定是满二叉树。完全二叉树常用于实现堆结构。

  1. 平衡二叉树(Balanced Binary Tree)

平衡二叉树是一种特殊的二叉树,其中每个节点的左右子树高度差不超过1。AVL树和红黑树是平衡二叉树的两种常见实现。

  1. 二叉查找树(Binary Search Tree BST)

二叉查找树满足以下性质:对于任意节点,其左子树上所有节点的值小于该节点的值,右子树上所有节点的值大于该节点的值。二叉搜索树常用于实现查找、插入和删除操作。

二叉查找树是一种非常重要的数据结构,许多高技树结构都是二叉查找树的变种,如AVL树和红黑树。

  1. 红黑树(Red-Black Tree)

红黑树是一种特殊的二叉查找树。红黑树的每个节点上都有存储表示节点的颜色。这些规则使红黑树保证了一种平衡,插入、删除、查找最坏的时间复杂度都是O(logn)。

红黑树的统计性能要好于平衡二叉树,Java中,HashMap、HashSet、TreeSet 等都有红黑树的应用。

  1. B树

B树是一种平衡的多路搜索树,每个节点可以包含多个子节点,通常用于磁盘存储系统。

特点:

  • 节点结构:每个节点最多有 m 个子节点,m−1 个键(M为树的阶数)。

  • 平衡性:所有叶子节点位于同一层。

  • 键值:节点中的键按升序排列,且每个键的左子树键值小于它,右子树键值大于它。

  • 操作:插入和删除通过分裂和合并节点保持平衡。

B树常用于数据库索引和文件系统,因为它能够高效地支持范围查询和顺序扫描。

  1. B+树

B+树是B树的变种,数据仅存储在叶子节点,内部节点仅用于索引。

特点:

  • 节点结构:内部节点有 m 个子节点和 m−1 个键,叶子节点包含所有键和数据。

  • 顺序访问:叶子节点通过指针连接,支持高效的范围查询。

  • 平衡性:所有叶子节点在同一层。

  • 操作:插入和删除通过分裂和合并节点保持平衡。

B+树广泛应用于数据库索引和文件系统,尤其是在需要频繁进行范围查询和顺序扫描的场景中。例如,MySQL的InnoDB存储引擎就使用B+树作为索引结构。

  1. B*树

B*树是B树的另一种变种,通过增加节点利用率减少分裂频率。

特点:

  • 节点结构:每个节点至少有 个子节点,比B树更紧凑。

  • 分裂策略:在插入时,B*树会尝试将键重新分配到兄弟节点,延迟分裂。

  • 平衡性:所有叶子节点在同一层。

  • 操作:插入和删除通过键重新分配和节点分裂保持平衡。

常用于需要高节点利用率的数据库和文件系统。

  1. R树

R树是一种用于空间数据索引的树结构,专门设计用于高效处理多维数据(如地理坐标、矩形区域等)。它广泛应用于地理信息系统(GIS)、数据库和计算机图形学等领域。

Java实现二叉树及遍历

  • 前序遍历

首选访问根节点,然后前序遍历其左子树,最后遍历其右子树,遍历左右子树时仍使用前序遍历。

  • 中序遍历

首选遍历根节点的左子树,然后访问根节点,最后中序遍历其右子树,遍历左右子树时仍使用中序遍历。

  • 后序遍历

首选后序遍历其左子树,然后后序遍历其右子树,最后访问根节点。遍历左右子树时仍使用后序遍历。

  • 层次遍历

层次遍历使用队列来实现,按层次从上到下、从左到右遍历节点。也是广度优先遍历。

我们使用java 递归实现二叉树的前序遍历、中序遍历、后序遍历、层次遍历。

/*** 二叉树节点实体类*/
@Data
public class BinaryTreeNode<T> {private T val;private BinaryTreeNode<T> left;private BinaryTreeNode<T> right;public BinaryTreeNode(T val) {this.val = val;}}/*** 二叉树遍历*/
public class BinaryTreeExample<T> {/*** 前序遍历* 前序遍历的顺序是:根节点 -> 左子树 -> 右子树。*/public static void preOrder(BinaryTreeNode<Integer> node, List<Integer> result){// 递归结束条件:节点为空则结束递归if(node == null){return;}//先访问根节点result.add(node.getVal());//遍历左子树preOrder(node.getLeft(), result);//遍历右子树preOrder(node.getRight(), result);}/*** 中序遍历* 中序遍历的顺序是:左子树 -> 根节点 -> 右子树。*/public static void inOrder(BinaryTreeNode<Integer> node, List<Integer> result){// 递归结束条件:节点为空则结束递归if(node == null){return;}//遍历左子树inOrder(node.getLeft(), result);//访问根节点result.add(node.getVal());//遍历右子树inOrder(node.getRight(), result);}/*** 后续遍历* 后序遍历的顺序是:左子树 -> 右子树 -> 根节点。*/public static void postOrder(BinaryTreeNode<Integer> node, List<Integer> result){// 递归结束条件:节点为空则结束递归if(node == null){return;}//遍历左子树postOrder(node.getLeft(), result);//遍历右子树postOrder(node.getRight(), result);//访问根节点result.add(node.getVal());}/*** 层序遍历*/public static void levelOrder(BinaryTreeNode<Integer> start, List<Integer> result){if(start == null){return;}//创建一个队列Queue<BinaryTreeNode> queue = new LinkedList<>();queue.offer(start);while (!queue.isEmpty()) {BinaryTreeNode<Integer> node = queue.poll();result.add(node.getVal());if (node.getLeft() != null) {queue.offer(node.getLeft());}if (node.getRight() != null) {queue.offer(node.getRight());}}}public static void main(String[] args) {BinaryTreeNode<Integer> node1 =  new BinaryTreeNode<>(1);BinaryTreeNode<Integer> node2 = new BinaryTreeNode<>(3);BinaryTreeNode<Integer> node3 = new BinaryTreeNode<>(2);BinaryTreeNode<Integer> node4 = new BinaryTreeNode<>(5);BinaryTreeNode<Integer> node5 = new BinaryTreeNode<>(4);BinaryTreeNode<Integer> node6 = new BinaryTreeNode<>(2);BinaryTreeNode<Integer> node7 = new BinaryTreeNode<>(6);BinaryTreeNode<Integer> node8 = new BinaryTreeNode<>(8);BinaryTreeNode<Integer> node9 = new BinaryTreeNode<>(7);BinaryTreeNode<Integer> node10 = new BinaryTreeNode<>(9);BinaryTreeNode<Integer> node11 = new BinaryTreeNode<>(6);BinaryTreeNode<Integer> node12 = new BinaryTreeNode<>(5);node1.setLeft(node2);node1.setRight(node3);node2.setLeft(node4);node2.setRight(node5);node3.setLeft(node6);node3.setRight(node7);node4.setLeft(node8);node4.setRight(node9);node5.setLeft(node10);node5.setRight(node11);node6.setLeft(node12);List<Integer> result1 = new ArrayList<>();List<Integer> result2 = new ArrayList<>();List<Integer> result3 = new ArrayList<>();List<Integer> result4 = new ArrayList<>();//前序遍历preOrder(node1, result1);System.out.println("前序遍历:"+result1.toString());//中序遍历inOrder(node1, result2);System.out.println("中序遍历:"+result2.toString());//后序遍历postOrder(node1, result3);System.out.println("后序遍历:"+result3.toString());//层序遍历levelOrder(node1, result4);System.out.println("层序遍历:"+result4.toString());}
}

运行结果如下:

前序遍历:[1, 3, 5, 8, 7, 4, 9, 6, 2, 2, 5, 6]
中序遍历:[8, 5, 7, 3, 9, 4, 6, 1, 5, 2, 2, 6]
后序遍历:[8, 7, 5, 9, 6, 4, 3, 5, 2, 6, 2, 1]
层序遍历:[1, 3, 2, 5, 4, 2, 6, 8, 7, 9, 6, 5]

总结

二叉树是一种非常重要的数据结构,广泛应用于各种算法和应用中。通过本文的介绍,您应该对树的基本概念、常见类型以及在Java中的实现有了更深入的理解。掌握树结构不仅有助于提高编程能力,还能帮助您更好地理解和设计复杂的算法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/27524.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Golang的数据库分库分表

# Golang的数据库分库分表 什么是数据库分库分表 数据库分库分表是指将单一的数据库拆分成多个库&#xff0c;每个库中包含多张表&#xff0c;以提高数据库的性能和可伸缩性。通常在大型应用中&#xff0c;单一的数据库往往无法满足高并发和海量数据的需求&#xff0c;因此需要…

FPGA开发,使用Deepseek V3还是R1(3):系统级与RTL级

以下都是Deepseek生成的答案 FPGA开发&#xff0c;使用Deepseek V3还是R1&#xff08;1&#xff09;&#xff1a;应用场景 FPGA开发&#xff0c;使用Deepseek V3还是R1&#xff08;2&#xff09;&#xff1a;V3和R1的区别 FPGA开发&#xff0c;使用Deepseek V3还是R1&#x…

探索Elasticsearch:文档的CRUD

在企业环境中&#xff0c;Elasticsearch对文档操作的支持不仅是实现高效搜索的关键&#xff0c;更是数据驱动决策的重要支柱。它通过强大的索引机制和灵活的查询语言&#xff0c;使企业能够实时处理和分析海量文档数据&#xff0c;迅速获取有价值的洞察&#xff0c;从而加速创新…

数组中的逆序对(C++)

目录 1 问题描述 1.1 输入描述&#xff1a; 1.2 示例1 1.3 示例2 2 解题思路 2.1 暴力解法 2.2 归并排序法 3 代码实现 3.1 暴力解法 3.2 归并排序法 4 代码解析 4.1 暴力解法 4.1.1 初始化 4.1.2 判断是否是逆序对 4.2 归并排序法 4.2.1 InversePairs 主函数 …

Spring Boot全局异常处理:“危机公关”团队

目录 一、全局异常处理的作用二、Spring Boot 实现全局异常处理&#xff08;附上代码实例&#xff09;三、总结&#xff1a; &#x1f31f;我的其他文章也讲解的比较有趣&#x1f601;&#xff0c;如果喜欢博主的讲解方式&#xff0c;可以多多支持一下&#xff0c;感谢&#x1…

数据集/API 笔记 新加坡相对湿度数据

data.gov.sg 数据时间范围&#xff1a;2016年11月 - 2025年3月 新加坡国家环境局 (NEA) 每分钟记录各个气象站的相对湿度数据&#xff0c;每五分钟更新一次。 数据由自动气象仪器采集&#xff0c;并在生成后立即自动发布。由于技术问题&#xff0c;数据可能会有缺失的情况。…

【前端基础】2、HTML的元素(基础说明)

一、元素概述 HTML本质是元素组成。 元素是网页的一部分。一个元素可以包含一个数据项&#xff0c;或者一块文本&#xff0c;或者一个图片&#xff0c;或者什么都不包含。 二、元素的组成 开始标签&#xff0c;结束标签&#xff0c;内容&#xff0c;组成一个完整元素。 三…

基于深度学习的网络摄像头图像实时分类实践:从理论到完整实现

引言&#xff1a;智能视觉感知的新可能 在人工智能技术蓬勃发展的今天&#xff0c;实时图像分类作为计算机视觉的基础任务之一&#xff0c;正在深刻改变着我们的生活。从智能手机的人脸解锁到无人超市的自动结算系统&#xff0c;从工业质检的缺陷检测到医疗影像的辅助诊断&…

Linux-计算机网络.udp

1.收发函数: read&#xff08;&#xff09;/write () ///通用文件读写&#xff0c;可以操作套接字。 recv(,0) /send(,0) ///TCP 常用套机字读写 recvfrom()/sendto() ///UDP 常用套接字读写 ssize_t recv(int sockfd, void *buf, size_t len, …

如何安装VM虚拟机

安装 VMware 附官方下载链接&#xff08;VM 17 pro&#xff09;&#xff1a;https://download3.vmware.com/software/WKST-1701-WIN/VMware-workstation-full-17.0.1-21139696.exe 打开下载好的VMware Workstation 17 Pro安装包&#xff1b; 点击下一步&#xff1b; 勾选我接…

js的简单介绍

一.javascript&#xff08;是什么&#xff09; 是一种运行在客户端(浏览器)的编程语言&#xff0c;实现人机交互效果 作用 网页特效&#xff08;监听客户的一些行为让网页做出对应的反馈&#xff09;表单验证(针对表格数据的合法性进行判断)数据交互(获取后台的数据&#xf…

绕过 RAG 实时检索瓶颈,缓存增强生成(CAG)如何助力性能突破?

编者按&#xff1a; 你是否曾经遇到过这样的困扰&#xff1a;在开发基于 RAG 的应用时&#xff0c;实时检索的延迟让用户体验大打折扣&#xff1f;或者在处理复杂查询时&#xff0c;检索结果的不准确导致回答质量不尽如人意&#xff1f; 在当前大语言模型应用大规模落地的背景下…

【Java SE】面向对象编程(基础)

面向对象编程&#xff08;基础&#xff09; 目录 1.类与对象的关系 2.对象在内存中的存在形式 2.2 注意事项&#xff08;1&#xff09; 2.3 注意事项&#xff08;2&#xff09; 3.对象的创建方式 4.变量 4.1 成员变量 4.1.1 语法格式 4.1.2 说明 4.2 局部变量 4.2.1…

excel 斜向拆分单元格

右键-合并单元格 右键-设置单元格格式-边框 在设置好分割线后&#xff0c;你可以开始输入文字。 需要注意的是&#xff0c;文字并不会自动分成上下两行。 为了达到你期望的效果&#xff0c;你可以通过 同过左对齐、上对齐 空格键或使用【AltEnter】组合键来调整单元格中内容的…

LeetCode 21. 合并两个有序链表(Python)

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] 示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] 输出&#xff1a;[] 示例 3&#xff1a; 输…

Linux下安装VS Code

Centos 7 https://blog.csdn.net/weixin_63790642/article/details/132927888 安装存储库 sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc密钥 sudo sh -c echo -e "[code]\nnameVisual Studio Code\nbaseurlhttps://packages.microsoft.com/yum…

【软考-架构】2.1、操作系统概述-进程管理-同步互斥

✨资料&文章更新✨ GitHub地址&#xff1a;https://github.com/tyronczt/system_architect 文章目录 操作系统知识操作系统概述进程组成和状态&#x1f4af;考试真题前趋图进程资源图&#x1f4af;考试真题问题1问题2 ✨【重点】进程同步与互斥✨&#x1f4af;考试真题问题…

养老小程序方案详解居家养老小程序系统

养老小程序&#xff0c;上门居家养老小程序&#xff0c;用户端护工端小程序&#xff0c;管理后台。php开发语言&#xff0c;可源码搭建&#xff0c;二次开发或者定制开发。 一 用户端&#xff1a;小程序 核心功能模块&#xff1a;用户完善个人健康档案&#xff0c;在线选择服…

基于NI USRP 硬件的下一代O-RAN研究测试台​

目录 基于NI SDR硬件的下一代O-RAN研究测试台​挑战&#xff1a;解决方案&#xff1a; 基于NI SDR硬件的下一代O-RAN研究测试台​ “OAIC提供了一个开放平台&#xff08;包括软件架构、库和工具集&#xff09;&#xff0c;用于对基于AI的无线接入网(RAN)控制器进行原型开发和测…

磁盘空间不足|如何安全清理以释放磁盘空间(开源+节流)

背景&#xff1a; 最近往数据库里存的东西有点多&#xff0c;磁盘不够用 查看磁盘使用情况 df -h /dev/sda5&#xff08;根目录 /&#xff09; 已使用 92% 咱们来开源节流 目录 背景&#xff1a; 一、开源 二、节流 1.查找 大于 500MB 的文件&#xff1a; 1. Snap 缓存…