常见的数据结构及应用

news2025/1/22 15:55:24

文章目录

  • 前言
  • 数据结构介绍
    • 数组
    • 链表
    • 队列和栈
  • 总结

前言

数据结构是计算机存储、组织数据的方式。在工作中,我们通常会直接使用已经封装好的集合API,这样可以更高效地完成任务。但是作为一名程序员,掌握数据结构是非常重要的,因为它可以帮助我们更好地理解和设计算法,从而提高程序的效率和可靠性。本文将对常见的几种数据结构进行介绍,通过了解这些数据结构的特点和优势,可以更好地在不同场景下选择合适的数据结构。

数据结构介绍

常见的数据结构大体分为两种类型:线性和非线性。

线性数据结构见名思义,整体结构的图像是一条直线。包括数组、链表、栈、队列等。
非线性数据结构包括,树、堆、图等。

数组

数组是由多个元素组成的一个集合,表现形式如下图

在这里插入图片描述

在内存中存储数组的空间是连续的,每个元素占据一定的内存空间,这也是为什么在声明数组时要指定长度,不然不知道要占用多少空间。以 Java 语言为例,当声明一个数组后,数组变量会指向数组对象的起始地址,也就是第一个元素的位置,如下图

在这里插入图片描述

以此看来,当查询数组中的某个元素时,通过下标就可以计算出这个元素的内存地址,比如想查找下标为2的元素,那么arr[2]的内存地址 = arr的内存地址 + 2 * 元素大小,也就可以直接通过内存地址访问元素,时间复杂度为O(1)。

但是,数组也会带来一个问题:由于数组长度是固定的,所以在添加或删除元素时会涉及到创建新的数组来替换原数组,导致复杂度较高。例如,下面的代码演示了如何在数组末尾添加一个元素:

int[] arr = {1, 2, 3, 4, 5};  
  
arr[arr.length] = 6; // 将要添加的元素放到数组的最后一个位置  
  
int[] newArr = new int[arr.length + 1]; // 创建一个新的数组,长度加1  
  
for (int i = 0; i < newArr.length; i++) {  
    newArr[i] = arr[i]; // 将原数组中的元素复制到新数组中  
}  
  
arr = newArr; // 使用新数组替换原数组

示例代码在内存中的活动如下图

在这里插入图片描述

在 Java 中有很多集合的底层实现都是基于数组,例如大家常用的 ArrayList、Vector、HashMap、ArrayBlockingQueue等等。

链表

链表由一系列结点组成,每个节点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个节点地址的指针域。以 Java 为例,一个节点的结构是这样表示的:

public class Node<T> {

    //存储数据元素的数据域
    private T value;

    //下一个节点地址的指针域
    private Node next;
}

每个元素的指针指向下一个元素,从而形成链表,表现形式如下图。

在这里插入图片描述

与数组不同,链表在内存中是非连续的空间,可以充分利用计算机内存空间,实现灵活的内存动态管理,解决了数组需要预先知道数据大小的缺点。其在内存中的存储如下图

在这里插入图片描述

相比于数组,链表的插入和删除操作可以达到O(1)的复杂度(只需要将链尾的指针指向下个节点或者指向null即可),但是查找一个节点或者访问特定编号的节点则需要O(n)的时间。

上面介绍的是单向链表,单向链表有个缺点:只能只能从头到尾遍历。如果要删除倒数第二个节点,只能从头遍历。为了更加灵活的操作和更高的效率,就有了双向链表,其结构表示如下图

在这里插入图片描述

如果结构为双向链表,要删除倒数第二个节点,只用找到尾节点的前面一个节点并删除即可。Java 中的 LinkedList 就是一个双向链表的实现。

队列和栈

数组和链表的关注点主要聚焦于数据的存储结构和访问方式,而队列和栈关注的则是数据的处理顺序和逻辑,有自己的特点。

队列的特点是先进先出(FIFO):第一个进入队列的元素会第一个被访问或取出,或者说在添加元素时在队尾排队依次入队,在队头依次出队。其表现形式如下图

在这里插入图片描述

栈的特点是先进后出(FILO):第一个入栈的元素最后一个被访问或被取出,或者说最后一个入栈的元素会第一个被访问或被取出。栈只允许在栈顶进行插入和删除操作。

有一个很形象的描述就是:可以将栈想象成一个弹夹,最先装入的子弹会被压入底部,而射出时则是从顶部弹出。

在这里插入图片描述

两者的底层实现可以根据具体需求和场景选择数组或链表作为底层数据结构。例如 Java 中的 ArrayBlockingQueue 是通过数组实现的阻塞队列,LinkedBlockingQueue 通过队列实现的非阻塞队列。

树是一种非线性结构,是由n个有限节点组成一个具有层次关系的集合。树也有很多类型,比如二叉树、平衡树、2-3-4树、红黑树、B树、B+树。

二叉树是每个节点最多有两个子树的树结构,通常用于实现二叉查找树,其特点为:左子节点的值小于根节点的值,右子节点的值大于根节点的值。以 Java 为例,一个二叉查找树的结构是这样表示的:

public class Node {

    //当前节点的值
    private int value;

    //父节点、左子节点、右子节点
    private Node parent,left,right;

}

表现形式如下图

在这里插入图片描述

其查询的时间复杂度为O(log n),相对于链表,查询效率大大提升。但是在最坏情况下可能会退化成O(n),比如下面这种情况

在这里插入图片描述


为了避免这种情况,诞生了AVL树。AVL树是一种自平衡的二叉查找树,在进行插入和删除操作时,会通过左旋或者右旋自动调整自身的结构,确保每个节点的左右子树的高度差不超过1,从而保持树的平衡,也保障了查询的时间复杂度为O(log n)。

以下图为例,当插入节点5时,节点7左右子树的高度差为2,这时候节点7就需要进行右旋保持树的平衡。

在这里插入图片描述
右旋就是:以某个节点为旋转点,其左子节点变为其父节点,左子节点的右子节点变为其左子节点,右子节点不变。
同理,左旋就是:以某个节点为旋转点,其右子节点变为其父节点,右子节点的左子节点变为其右子节点,左子节点不变。


虽然AVL通过旋转保持树的平衡,但是在插入和删除频繁的场景中,频繁的旋转会导致性能下降,为解决此问题红黑树被提出。

红黑树大家应该都比较耳熟,面试的时候应该经常会被问到,但是理不理解是另一回事。

红黑树也是自平衡的二叉查找树,它是通过节点颜色来保证树的平衡的。相对AVL,红黑树较难被理解,第一疑惑就是:“不也是左旋右旋吗?还这么麻烦,节点颜色变来变去,迷惑谁呢?”。

红黑树后面专门写一篇文章介绍,这里先给结论:红黑树的旋转次数相对于AVL树来说较少,因此在插入、删除等操作较多的情况下,通常使用红黑树,比如大家都知道的HashMap。下图显示的是按顺序插入9, 7, 6, 10, 5, 8, 4, 2, 1, 0的AVL树和红黑树,可以看到两者在结构上存在一定的差异。

在这里插入图片描述


上面说的几种树都是二叉树,即每个节点只有两个分支,并且都都是有序的。因为只有两个分支,所以这也是二叉树的通病,当数据越来越多的时候,树的高度也会越高,这种情况就不适合数据库和文件系统这种场景了。

上面提到的几种树结构都是二叉树,每个节点只有两个子节点,并且都是有序的。当数据量不断增加时,二叉树的高度也会逐渐增加,从而导致查询效率降低,并且在有磁盘I/O操作的场景下,树越高越不利于查询。

为了解决上述问题,采用多叉树结构,可以有效地降低树的高度,提高查询效率。

常见的多叉树有2-3-4树、B树和B+树,通常在数据库和文件系统中会使用到,其表现形式如下图。

在这里插入图片描述

B+树是B树的一种扩展,它更适合用于磁盘或其他存储设备中。在B+树中,非叶子节点不保存数据信息,只保存关键字和子节点指针,这样会存储更多有效数据,比如索引。同时,每个叶子节点都指向相邻叶子节点的指针,这样的话在数据库范围查询会变得非常高效。

堆是一种特殊的树形数据结构,其特点为:每个节点都大于或等于(小于或等于)其每个子节点。

常见的堆有二叉堆、斐波那契堆等,二叉堆是一种完全二叉树,可以分为最大堆和最小堆,最大堆中的每个节点都大于或等于其子节点,最小堆中的每个节点都小于或等于其子节点。下图左为最大堆的表示,右不符合为一个完全二叉树(依次从左到右插入的节点为完全二叉树)。

在这里插入图片描述

堆通常被用作优先队列,因为堆的根节点总是最大的或最小的。

总结

很多编程语言都提供了不同类型的集合类,以 Java 为例,我们常用的集合有List、Set、Queue、Map,其底层的实现就是数组、链表或树这几种数据结构。所以通过了解数据结构,我们可以更好地选择和使用这些集合,甚至可以自行设计更高效的数据结构来解决问题。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【EI会议征稿】2024年第四届人工智能、自动化与高性能计算国际会议(AIAHPC 2024)

2024年第四届人工智能、自动化与高性能计算国际会议&#xff08;AIAHPC 2024&#xff09; 2024 4th International Conference on Artificial Intelligence, Automation and High Performance Computing 2024第四届人工智能、自动化与高性能计算国际会议(AIAHPC 2024)将于202…

搭建伪分布式Hadoop

文章目录 一、Hadoop部署模式&#xff08;一&#xff09;独立模式&#xff08;二&#xff09;伪分布式模式&#xff08;三&#xff09;完全分布式模式 二、搭建伪分布式Hadoop&#xff08;一&#xff09;登录虚拟机&#xff08;二&#xff09;上传安装包&#xff08;三&#xf…

通过 Splashtop Enterprise 实现更高的效率

远程工作的出现不仅重塑了我们的传统工作模式&#xff0c;而且还使远程访问和支持解决方案在确保运营连续性和效率方面的关键作用浮出水面。 Splashtop Enterprise 已帮助企业实现远程工作和 IT 远程支持的无缝远程访问&#xff0c;并已被证明是许多组织不可或缺的工具。 在本…

综合电商商城小程序的作用是什么

综合电商顾名思义就是什么商品都卖&#xff0c;涵盖的品牌、种类、数量非常庞大&#xff0c;线下门店规模也相当可以&#xff0c;在同城场景中有较高的需求度。 然而在实际经营中&#xff0c;综合商品经营商家还是会面临一些痛点。 通过【雨科】平台搭建综合电商商城小程序全面…

NProgress进度条的使用

1 下载nprogress npm install --save nprogress 2.然后在 router/index.js里写上以下几行代码 import NProgress from "nprogress"; // 导入 nprogress模块import "nprogress/nprogress.css"; // 导入样式&#xff0c;否则看不到效果NProgress.configure(…

如何规避企业内文件流转泄密风险?

由于企业内部业务流程复杂&#xff0c;研发、生产、销售等跨部门的不同人员有时需要交互数据&#xff0c;而不同的文件涉密程度不同&#xff0c;需要由不同涉密等级的人员进行处理。 为保障核心资料的安全&#xff0c;文件阅读权限管控系统为用户提供了灵活的内部文件流转功能&…

CleanMyMac X4.14.3中文版:时尚元素与高效清理的完美结合!

嗨&#xff01;小仙女们~&#x1f338;今天小编给大家介绍一款超级时尚的Mac清理神器——CleanMyMac X4.14.3中文版&#xff01; 想要让你的电脑焕然一新&#xff0c;提升操作速度&#xff0c;还能拥有时尚元素的体验&#xff0c;那就赶紧来看看吧&#xff01; CleanMyMac X 2…

重生奇迹mu获取宠物的方法

现在很多游戏都有宠物&#xff0c;因为宠物的加入让游戏更加有趣&#xff0c;玩家可以带着宠物玩游戏&#xff0c;宠物还可以做出呆萌的鬼脸&#xff0c;让玩家感受到游戏的魅力&#xff0c;重生奇迹MU游戏也是有各种宠物。 在重生奇迹MU之中有各种宠物&#xff0c;这些宠物非…

CatBoost算法模型实现贷款违约预测

前言 此篇文章为整个Boost(提升方法)集成算法模型的终章&#xff0c;前几篇文章依次结合详细项目案例讲解了AdaBoost、GBDT、XGBoost、LighGBM共四个常用的集成算法模型&#xff0c;每一篇文章都包含实战项目以及可运行代码。仅通过看一遍文章不去实践是很难掌握集成算法模型的…

Com 信号值的超时替换

目录 1. 功能简介2. 如何配置 1. 功能简介 Com 模块提供了针对信号的超时替换处理&#xff0c;如下图所示。提供两种方式 REPLACESUBSTITUTE REPLACE: 信号值由ComSigInitValue 进行替换 SUBSTITUE: 信号值由ComTimeoutSubstitutionValue 进行替换。 2. 如何配置 点击 Vie…

企业做一个VR全景,拍摄制作的费用有哪些?

自互联网时代以来&#xff0c;抖音、快手、微信、微博、小红书等渠道成为了客户新的沟通方式&#xff0c;越来越多的企业客户在网上沟通、在网上了解产品、在网上考察公司情况&#xff0c;为了让客户在网上看得清、看得懂&#xff0c;VR赋能企业线上沉浸式营销&#xff0c;VR全…

基于springboot实现大学生社团活动平台项目【项目源码+论文说明】计算机毕业设计

摘要​​​​​​​ 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;网络管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&a…

vscode配置c++和opencv环境

因为想要用c刷题&#xff0c;但是之前的vs被重装的时候删除了&#xff0c;DEVc实在是不好看的界面&#xff0c;于是就想起了之前写html的vscode&#xff0c;没想到配置环境花了一整天&#xff0c;还总是报错&#xff0c;也许是电脑配置不一样&#xff0c;所以就出了问题吧&…

Knowledge and Process .xls

Knowledge and Process .xls 10知识领域 5项目管理过程组

滚珠丝杆的工作原理是什么?

滚珠螺杆的工作原理是利用滚珠在螺杆与螺母之间做运动&#xff0c;将传统螺杆的滑动接触转换为滚动接触&#xff0c;再将螺帽内的滚珠回转运动转为直线运动。它主要由①丝杆②螺母③滚珠 三个主要部分组成。 丝杆和螺母的表面存在螺旋线&#xff0c;当丝杆旋转时&#xff0c;螺…

【C#】【winform】Microsoft Visual Studio Installer Project 打包应用程序全部过程

提示&#xff1a;只针对扩展包来完成打包的工作过程。 文章目录 前言一、Microsoft Visual Studio Installer Project 是什么&#xff1f;二、安装1.安装Microsoft Visual Studio Installer Project 三、安开始打包1.添加setup1.在解决方案上面右键&#xff0c;添加-新建项目2.…

k8s-18 认证授权

Authentication (认证) 认证方式现共有8种&#xff0c;可以启用一种或多种认证方式&#xff0c;只要有一种认证方式通过&#xff0c;就不再进行其它方式的认证。通常启用X509 Client Certs和Service Accout Tokens两种认证方式 Kubernetes集群有两类用户:由Kubernetes管理的Ser…

Flow深入浅出系列之使用Kotlin Flow自动刷新Android数据的策略

Flow深入浅出系列之在ViewModels中使用Kotlin FlowsFlow深入浅出系列之更聪明的分享 Kotlin FlowsFlow深入浅出系列之使用Kotlin Flow自动刷新Android数据的策略 Flow深入浅出系列之使用Kotlin Flow自动刷新Android数据的策略 讨论在Android应用程序中使用Kotlin Flow高效加载…

Linux——生产者消费者模型

目录 一.为何要使用生产者消费者模型 二.生产者消费者模型优点 三.基于BlockingQueue的生产者消费者模型 1.BlockingQueue——阻塞队列 2.实现代码 四.POSIX信号量 五.基于环形队列的生产消费模型 一.为何要使用生产者消费者模型 生产者消费者模式就是通过一个容器来解决生…

面试官:做过性能优化?我:任务切片!

给大家推荐一个实用面试题库 1、前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;web前端面试题库 代码背景 本次分享基于一次线上环境的卡顿事故&#xff0c;客户数据体量过大导致的页面卡顿甚至页面直接崩溃的问题…