线性表入门

封面:线性表入门.png

王有志,一个分享硬核Java技术的互金摸鱼侠
加入Java人的提桶跑路群:共同富裕的Java人

从今天开始就进入到数据结构的部分了,整体分为3个部分:线性表,树和图,从认识每种数据结构到它们的高级应用。今天我们先从最简单的线性表和数组开始。

什么是线性表?

线性表是我们工作中最常用的数据结构之一,同时它也是我们接触到的最简单的数据结构。
根据操作节点的自由度,我们可以将线性表分为两大类:非受限线性表受限线性表

  • 非受限线性表:数组,链表
  • 受限线性表:栈,队列

除此之外,字符串也是一种特殊的线性表。
在频繁的使用过程中,你有没有思考过什么是线性表?我们一起来看下百度百科中线性表的定义:

线性表(linear list),是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。

线性表的概念还是很容易理解的,接着来看点头疼的:

线性表中的个数n定义为线性表的长度,n=0时称为空表。在非空表中每个数据元素都有一个确定的位置,如用ai表示数据元素,则i称为数据元素ai在线性表中的位序。线性表的相邻元素之间存在着序偶关系。如用(a1,…,ai-1,ai,ai+1,…,an)表示一个顺序表,则表中ai-1领先于ai,ai领先于ai+1,称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素。当i=1,2,…,n-1时,ai有且仅有一个直接后继,当i=2,3,…,n时,ai有且仅有一个直接前驱。

这些看起来是不是就有些头疼了?我们举个简单的例子,糖葫芦都吃过吧?如果我说糖葫芦就是一个线性表呢?图1:线性糖葫芦.png
我们来看看糖葫芦是不是符合线性表的定义:

  • 相同特性的数据元素:都是山楂;
  • 有限:总共5个山楂;
  • 序列:给山楂编上号就是完整的序列。

很多小伙伴可能忘记了序列的特点,序列存在顺序关系(可以是混乱的顺序,但是要固定)和排成一列(不会有分支,前后一对一的关系)
通过这串糖葫芦,也给出位序,前驱节点和后继节点的解释:

  • 位序:山楂在签子上确定位置的编号,就是通过这个编号可以找到指定的山楂;
  • 前驱节点:以2号山楂为例,排在2号前面的都是前驱节点;
  • 直接前驱节点:还是2号山楂,排在2号山楂,并且紧挨2号山楂的1号山楂就是直接前驱节点;
  • 后继节点:和前驱节点反过来;
  • 直接后继节点:和直接前驱节点反过来。

再通俗点解释,可以用“一根线”穿起来的相同物件(元素),并保持固定顺序的就是线性表。这样理解起来是不是比定义中的数学符号简单多了?

数组

知道了什么是线性表之后,我们来看线性表中最简单的数据结构:数组。
还记得我们在预备知识:概念和存储结构#物理存储结构提到的顺序存储结构吗?数组正是使用了顺序存储结构
另外在预备知识:概念和存储结构#内存地址中我们提到过每块内存都有自己的编号。这种顺序存储结构加上内存编号,使得数组具有了强大的随机存取能力。

数组的优点

数组最大的优点就是随机存取的能力,换句话说就是在数据中查找指定下标的元素速度非常快
因为计算机可以通过一步简单的计算得到存储该元素的内存地址:起始地址+下标X类型大小。这是不是数组下标从零开始的原因之一呢?

数组的缺点

计算机的世界中没有能解决一切问题的“银弹”,随机存取的能力不仅仅给了数组快速查找元素的资本,也使得数组在插入和删除元素后必须要“整理”内存,顺序存储结构。
数组在插入元素后,为了保持随机存取的特性,必须要向后移动元素。
图2:数组插入元素.png
数组在删除元素后,为了保持随机存取的特性,必须要向前移动元素。
图3:数组删除元素.png
当然,也并不是全部的插入删除都要移动元素。最好的情况下,在数组的尾部插入和删除元素,不需要移动任何元素,此时的时间复杂度是 O ( 1 ) O(1) O(1)。如果是最坏的情况,需要在数组的头部插入和删除元素,则要移动整个数组,此时的时间复杂度是 O ( n ) O(n) O(n)
除了数组的插入和删除外,还有一种情况我们不得不考虑,如果我们在插入元素时,紧邻数组的内存已经被分配了怎么办?

数组的扩容

我们先来看一段代码:

// 第一种
int numbers1 = {0, 1, 2};// 第二种
int numbers2 = new int[3];// 第三种
int[] numbers3 = {};
numbers3[0] = 0;  
numbers3[1] = 1;
numbers3[2] = 2;

这3种创建数组的代码,哪个会有编译时异常?哪个会有运行时异常?
答案是,都能通过编译,但是第三种在运行时会抛出ArrayIndexOutOfBoundsException异常。
强制要求创建数组时进行初始化或者指定数组大小,是为了能够给数组分配合适的内存。但是这么做就带来另一个问题,创建数组时,大小已经固定,如果想添加更多的元素该怎么办?
相信你一定非常熟悉ArrayList了吧?
ArrayList正是Java中提供的可动态扩容的数组,它的底层是Object[],扩容的方式也非常的“粗暴”,当数组大小不足时,重新申请内存(1.5倍),将原数组元素拷贝到新的数组上,并修改引用。

结语

数组的内容就到此结束了,仅仅从数据结构的角度来看数组,还是非常简单的。
可能很多小伙伴会说,工作中都是使用ArrayList了,数组要退出舞台了。
我的想法是,大部分场景选择ArrayList是没有任何问题的,在追求极致性能,且没有插入删除的场景时,数组或许会是一个不错的选择。

练习

  • 尝试实现一个动态数组
  • 1.两数之和
  • 53.最大子数组和
  • 88.合并两个有序数组

如果本文对你有帮助的话,还请多多点赞支持。如果文章中出现任何错误,还请批评指正。最后欢迎大家关注分享硬核Java技术的金融摸鱼侠王有志,我们下次再见!

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

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

相关文章

C# Linq+ValueTuple(元祖),成为Linq高手!

文章目录 前言简单使用:能被2整除ValueTuple使用:两数相加等于4不使用元祖使用元祖排序 基于类的LinqGroupByJoinDistinct去重普通去重选择去重 集合去重ExceptIntersectUnion 总结 前言 Linq是C# 最强语法之一,和委托,get set并列(在我的心中)。我很早就听说了Lin…

基于JavaWeb+BS架构+SpringBoot+Vue智能停车计费系统的设计和实现

基于JavaWebBS架构SpringBootVue智能停车计费系统的设计和实现 文末获取源码Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 文末获取源码 Lun文目录 1 绪 论 1 1.1 研究背景 1 1.2 研究意义 1 1.3 系统主要功能 1 1.4 拟解决…

Blazor快速开发框架Known-V2.0.0

Known2.0 Known是基于Blazor的企业级快速开发框架,低代码,跨平台,开箱即用,一处代码,多处运行。 官网:http://known.pumantech.comGitee: https://gitee.com/known/KnownGithub:ht…

Ubuntu22.04开机左上角下划线闪烁不开机

按下CtrlAltF2,打开TTY系统,然后通过用户名和密码登录,随后使用 sudo apt --fix-broken install 根据提示排除错误信息,然后使用apt安装lightdm安装就行。 tips:当使用EasyConnect的时候,你可能参考了下面这篇文章知…

130基于MATLAB并结合IBD算法的盲迭代反卷积法进行图像复原

基于MATLAB并结合IBD算法的盲迭代反卷积法进行图像复原 ,输出复原前后图像,PSF频谱结果。程序已调通,可直接运行。 130 matlab盲迭代反卷积IBD (xiaohongshu.com)

【Kafka-3.x-教程】-【三】Kafka-Broker、Kafka-Kraft

【Kafka-3.x-教程】专栏: 【Kafka-3.x-教程】-【一】Kafka 概述、Kafka 快速入门 【Kafka-3.x-教程】-【二】Kafka-生产者-Producer 【Kafka-3.x-教程】-【三】Kafka-Broker、Kafka-Kraft 【Kafka-3.x-教程】-【四】Kafka-消费者-Consumer 【Kafka-3.x-教程】-【五…

【Redis】Redis持久化方式

Redis 中有两种持久化方式,分别为 RDB 和 AOF。 RDB RDB 全称 Redis Database Backup file,也叫做 Redis 数据快照。简单来说就是把 Redis 中的数据记录到磁盘中。当 Redis 实例故障重启后,从磁盘读取快照文件,恢复数据。 RDB有…

ESP32S3+HX8347+RGB运行LVGL例程

之前用3线SPI驱动的HX8347屏其实是一个RGB屏,SPI只是用来给RGB屏幕的做配置的,当然也可以用来驱动屏幕,但是3线SPI驱动能力终究有限。本文谈一下用RGB方式来驱动。 RGB接线比较多,为此做了个转接板: 一、源码 1、scre…

超维空间M1无人机使用说明书——53、ROS无人机二维码识别与降落——V2升级版本

引言:使用二维码引导无人机实现精准降落,首先需要实现对二维码的识别和定位,可以参考博客的二维码识别和定位内容。本小节主要是通过获取拿到的二维码位置,控制无人机全向的移动和降落,本小节再V1版本的基础上增加了动…

实现稳定的联合显著性检测和联合目标分割

1 Title Toward Stable Co-Saliency Detection and Object Co-Segmentation(Bo Li; Lv Tang; Senyun Kuang; Mofei Song; Shouhong Ding)【IEEE Transactions on Image Processing 2022】 2 Conclusion This paper present a novel model for simultaneous stable co-saliency…

基础_函数_流程函数

流程函数也是很常用的一类函数,可以在SQL语句中实现条件筛选,从而提高语句效率.

【HarmonyOS4.0】第七篇-ArkUI系统组件(二)

鸿蒙开发系统组件详细剖析 五、进度条组件 进度条也是UI开发最常用的组件之一,ArkUI开发框架提供了两种类型的进度条: Progress 和LoadingProgress ,前者可以精准指定进度,后者表示正在加载的状态,我们接下来对它们分…

Spring MVC 参数接收

参数接收 Springmvc中,接收页面提交的数据是通过方法形参来接收: 处理器适配器调用springmvc使用反射将前端提交的参数传递给controller方法的形参 springmvc接收的参数都是String类型,所以spirngmvc提供了很多converter(转换器…

LightGBM原理和调参

背景知识 LightGBM(Light Gradient Boosting Machine)是一个实现GBDT算法的框架,具有支持高效率的并行训练、更快的训练速度、更低的内存消耗、更好的准确率、支持分布式可以处理海量数据等优点。 普通的GBDT算法不支持用mini-batch的方式训练,在每一次…

Google Pixel 与 iPhone手机:哪个更好?

iPhone稳定可靠,Pixel性价比高且创新。两者各有千秋,满足不同需求 谷歌的 Pixel 手机是 Android 最接近 iPhone 的手机,也是真正原生的Android手机。在iPhone 15 Pro Max 与华为 Mate 60 Pro的比较中不难看出,iPhone依然有着极强…

杨中科 .NETCORE 异步编程

一、 为什么需要异步编程 异步点餐的优点:能同时服务多个客人 异步点餐一定会提升单个客户点餐速度吗? 答案理所当然:不能 图片美化服务例子服务器能够同时服务的请求数量有限 void BeautifyPic (File photo, Response response) {byte[] …

Nginx配置反向代理实例二

Mac 安装Nginx教程 Nginx配置反向代理实例一 提醒一下:下面实例讲解是在Mac系统演示的; 反向代理实例二实现的效果 使用nginx 反向代理,根据访问的地址跳转到不同端口的服务中 nginx 监听端口为81; 访问地址1:http:/…

postman使用-06断言

文章目录 一、断言定义二、 常用的断言三、断言-状态码(1)单一状态码断言:Status code:Code is 200 检查返回的状态码是否为200原始模板:修改后:括号里的200也可以改成自己要断言的状态码具体步骤:断言成功…

字体图标 iconFont

字体图标使用场景︰主要用于显示网页中通用、常用的一些小图标 精灵图是有诸多优点的,但是缺点很明显。 图片文件还是比较大的。图片本身放大和缩小会失真。一旦图片制作完毕想要更换非常复杂。 此时,有一种技术的出现很好的解决了以上问题&#xff0c…

springboot虹软人脸识别集成

准备工作 虹软开放平台中创建一个新的应用 虹软开发平台【点我跳转】 开始上代码 基本配置 将下载的jar包放到src同级目录下 <!-- 虹软--><dependency><groupId>com.arcsoft.face</groupId><artifactId>arcsoft-sdk-face</artifactI…