线性表Ⅱ- 顺序存储
想看博主whywait的更多同系列查漏补缺必看文?点击传送门,点击关注不迷路哦
进来看糟老头子的直接进入《插入和删除》部分!
在上一篇文章中,我们介绍了线性表的一些基础知识;接下来,我将介绍一下线性表中的两种表示方法:顺序表示方法和链式表示方法。
世界上没有什么东西是完美无缺的,两种表示方法有他们各自的优缺点。我们将在介绍完两种表示方法之后,对比两种表示方法的优缺点以及他们的适用场景。
下面我们开始介绍线性表的顺序表示。
定义
线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素。
注意加粗字体!注意加粗字体!注意加粗字体!
性质
1. 物理位置相邻
由于线性表顺序表示的定义 - 一组地址连续的存储单元 依次 存储线性表的数据元素。
下面介绍一些由定义直接得到的性质。
假设线性表的每个元素需占用k个内存,并以所占的第一个单元的存储地址作为数据元素的存储位置。则线性表中第
i
+
1
i+1
i+1个数据元素的存储位置
L
O
C
(
a
i
+
1
)
LOC(a_{i+1})
LOC(ai+1)和第i个数据元素的存储位置
L
O
C
(
a
i
)
LOC(a_i)
LOC(ai)之间满足下列关系:
L
O
C
(
a
i
+
1
)
=
L
O
C
(
a
i
)
+
k
LOC(a_{i+1}) = LOC(a_i) + k
LOC(ai+1)=LOC(ai)+k
一般来说,线性表的第
i
i
i个数据元素
a
i
a_i
ai的存储位置为
L
O
C
(
a
i
)
=
L
O
C
(
a
1
)
+
(
i
−
1
)
∗
k
LOC(a_{i}) = LOC(a_1) + (i-1) * k
LOC(ai)=LOC(a1)+(i−1)∗k
式中
L
O
C
(
a
1
)
LOC(a_1)
LOC(a1)说线性表的第一个数据元素
a
1
a_1
a1的存储位置,通常称作线性表的起始位置或基地址。
线性表的这种机内表示称作线性表的顺序存储结构或顺序映像,通常,称这种存储结构的线性表为顺序表。
顺序表的特点是,为表中相邻的元素 a i a_i ai和 a i + 1 a_{i+1} ai+1赋以相邻的存储位置 L O C ( a i ) LOC(a_i) LOC(ai)和 L O C ( a i + 1 ) LOC(a_{i+1}) LOC(ai+1)。换句话说,以元素在计算机内“物理位置相邻”来表示线性表中数据元素之间的逻辑关系。
2. 随机存取
首先我们要知道,随机存取到底是一个什么概念。
所谓随机存取,就是只要我们确定了存储线性表的起始位置,线性表中任意数据元素都可随机存取。
举个例子来说,因为顺序表在计算机内物理位置相邻,所以,我们只要知道顺序表的起始位置(基地址),我们就可以晓得顺序表上的第 i i i个元素的地址(联想 L O C ( a i ) = L O C ( a 1 ) + ( i − 1 ) ∗ k LOC(a_{i}) = LOC(a_1) + (i-1) * k LOC(ai)=LOC(a1)+(i−1)∗k)。由 i i i的任意性,顺序表上的任意数据元素就可随机存取啦。
则,线性表的顺序存储结构是一种随机存取的存储结构。(上面的举例也正是说明了这一点)
因为高级程序设计语言中的数组类型也有随机存取的特点,因此,我们通常都用数组来描述数据结构中的顺序存储结构。
值得注意的是,除特别声明外,数组的下标从 0 0 0开始。
操作
插入和删除
由定义我们知晓,顺序表中的每个元素在计算机内的物理位置相邻。
场景一:
我们可以如此想象,有一条很长很长的队伍,大家因为某种不可描述的原因,约定俗成的要将自己的胸膛要贴到前面的人的背(队首的人自然就没有前面的人可言)。
有个糟老头子,坏得很,想插队。但是呢,队伍里的人们都胸贴背背蹭胸的,他想插队到某个特定的人前面,唯一的方法,就是让那个人以及其后面的人,都往后挪一挪。
挪一挪说起来简单,却也暗含玄机。我们需要排在队伍最后头的先往后移一个位子,然后是倒数第二个,再是倒数第三个···如果特定的那个人直接后移,会造成什么结果呢?踩踏?肢体撞击?总之是terrible的事情。
在顺序表中,如果不按照上面方法说的留个空给糟老头子钻,会导致后面的元素被前面的元素覆盖了,然后被覆盖的可怜虫就再也找不到了···
场景二:
有个排在队伍里面的娃,觉得排在这么挤的队伍里面实在是无趣得很,于是决定摆脱队伍。于是他就走出了队伍,原来他站立的位子就留了个空。因为之前提到的不可描述的原因,自然是要把这个空给补上的。
怎么补呢?自然是排在前面的往前挪,然后后面的逐个跟上。直到又恢复成一幅不可描述的景象。
场景一对应的就是顺序表操作中的插入,场景二对应的就是顺序表操作中的删除。
从类比场景中我们可以非常明显的get到一个点:不论是插入还是删除,消耗的时间都主要是花费在移动元素上。换句话说,移动元素的操作为预估算法时间复杂度的基本操作。
而移动元素的个数取决于插入或删除元素的位置。假设在线性表的任何位置上插入或删除元素都是等概率的,通过计算期望,可发现在顺序存储结构的线性表中插入或删除一个数据元素,平均约移动表中一半元素。则两个操作的时间复杂度为 O ( n ) O(n) O(n).
其他操作
下面是一些其他操作的相关信息。
操作 | 相关信息 |
---|---|
求表长 | 时间复杂度为O(1) |
取第i个数据元素 | 时间复杂度为O(1) |
在顺序表I中查访是否存在和e相同的数据元素 | 最简便的方法是让e和l中的数据元素逐个比较,此算法的基本操作是“进行两个元素之间的比较” |
想看博主whywait的更多同系列查漏补缺必看文?点击传送门,点击关注不迷路哦
内容参考:《数据结构 (C语言版)》 严蔚敏、吴伟民