线性表结构下的增删查

111 阅读5分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情

我们了解到数据在代码中被处理和加工的最小单位动作是增、删、查。它们是深入学习数据结构的根基,通过“增删查”的操作,我们可以选择更合适的数据结构来解决实际工作中遇到的问题。

什么是数据结构

首先,我们简单探讨一下什么是数据结构。数据结构,从名字上来看是数据的结构,也就是数据的组织方式。在数据结构适用的场合中,需要有一定量的数据。如果数据都没有,也就不用讨论数据如何组织了。当我们有了一定数量的数据时,就需要考虑以什么样的方式去对这些数据进行组织了。

接下来,我将通过一个实际案例来帮助你更好地理解数据结构。假设你是一所幼儿园的园长,现在你们正在组织一场运动会,所有的小朋友需要在操场上接受检阅。那么,如何组织小朋友有序站队并完成检阅呢?

几个可能的方式是,让所有的小朋友站成一横排,或者让小朋友站成方阵,又或者让所有的小朋友手拉手,围成一个大圆圈等等。很显然,这里有无数种可行的组织方式。具体选择哪个组织方式,取决于哪一种能更好地展示出小朋友们的风采。

试想一下,当计算机要处理大量数据时,同样需要考虑如何去组织这些数据,这就是数据结构。类似于小朋友的站队方式有无数种情况,数据组织的方式也是有无数种可能性。

CgqCHl7OXiqAWO_nAKvmbV2Jtk4891 (1).gif

然而,在实际开发中,经过工程师验证并且能有效解决问题的高效率数据结构就比较有限了。事实上,只要我们把这些能真正解决问题的数据结构学会,就足以成为一名合格的软件工程师了。

什么是线性表

好了,铺垫完数据结构的基本概念后,我们就正式进入到这个课程中的第一个数据结构的学习,线性表。

线性表是 n 个数据元素的有限序列,最常用的是链式表达,通常也叫作线性链表或者链表。在链表中存储的数据元素也叫作结点,一个结点存储的就是一条数据记录。每个结点的结构包括两个部分:

  • 第一是具体的数据值;

  • 第二是指向下一个结点的指针。

在链表的最前面,通常会有个头指针用来指向第一个结点。对于链表的最后一个结点,由于在它之后没有下一个结点,因此它的指针是个空指针。链表结构,和小朋友手拉手站成一排的场景是非常相似的。

线性表对于数据的增删查处理

学会了线性表原理之后,我们就来围绕数据的增删查操作,来看看线性表的表现。在这里我们主要介绍单向链表的增删查操作,其他类型的链表与此雷同,我们就不再重复介绍了。

首先看一下增加操作。如下有一个链表,它存储了 10 个同学的考试成绩。现在发现这样的问题,在这个链表中,有一个同学的成绩忘了被存储进去。假设我们要把这个成绩在红色的结点之后插入,那么该如何进行呢?

其实,链表在执行数据新增的时候非常容易,只需要把待插入结点的指针指向原指针的目标,把原来的指针指向待插入的结点,就可以了。如下图所示:

CgqCHl8ESZuADqT5AABRo8Zc6TI733.png

代码如下:

js.next = p.next;

p.next = s;

接下来我们看一下删除操作。还是这个存储了同学们考试成绩的链表,假设里面有一个成绩的样本是被误操作放进来的,我们需要把这个样本删除。链表的删除操作跟新增操作一样,都是非常简单的。如果待删除的结点为 b,那么只需要把指向 b 的指针 (p.next),指向 b 的指针指向的结点(p.next.next)。如下图所示:

CgqCHl8ESbaAJi2xAAA-XJSjXw4037.png

代码如下:

p.next = p.next.next;

总结

线性链表结构的每个结点,由数据的数值和指向下一个元素的指针构成。根据结构组合方式的不同,除了单向链表以外,还有双向链表、循环链表以及双向循环链表等变形。

经过我们的分析,链表在增、删方面比较容易实现,可以在 O(1) 的时间复杂度内完成。但对于查找,不管是按照位置的查找还是按照数值条件的查找,都需要对全部数据进行遍历。

线性表的价值在于,它对数据的存储方式是按照顺序的存储。当数据的元素个数不确定,且需要经常进行数据的新增和删除时,那么链表会比较合适。链表的翻转、快慢指针的方法,是你必须掌握的内容。