2.线性结构-线性表
线性表
线性表是最常见、最简单的一种线性数据结构。
逻辑结构
线性表是n(n≥0)个具有相同特性的数据元素的有限序列,其中n表示线性表中数据元素的个数,称为线性表的长度。
n等于0时,线性表为空表。
线性表的逻辑结构具有以下特性:
- 除第一个元素a1外,每一个数据元素都有且仅有一个前驱。
- 除最后一个元素an外,每一个数据元素都有且仅有一个后继。
- 数据元素之间是有序的,数据元素的序号决定了它在表中的位置。
线性表的运算
只是线性表可以进行的部分运算,并不是所有的线性表都要实现这里列出的所有运算。
在实际应用中应根据需要实现与所要解决的问题相关的运算。
- 初始化线性表。
- 建立线性表。
- 清空线性表。
- 输出线性表的所有元素。
- 求线性表的长度。
- 判断线性表是否为空。
- 按照给定条件,查找数据元素。
- 读取线性表中的第i个元素。
- 在线性表第i个位置之前插入一个新的数据元素。
- 在指定数据元素之前插入一个新的数据元素。
- 删除线性表中第i个数据元素。
- 删除线性表中指定的数据元素。
- 查找线性表中第i个元素的前驱。
- 查找线性表中指定元素的前驱。
- 查找线性表中第i个元素的后继。
- 查找线性表中指定元素的后继。
- 将两个线性表合并成一个线性表。
- 将一个线性表拆分成两个或多个线性表。
顺序存储 VS 链式存储
查找 | 更新 | 插入 | 删除 | |
---|---|---|---|---|
顺序存储 | O(1) | O(1) | O(n) | O(n) |
链式存储 | O(n) | O(1) | O(1) | O(1) |
物理存储结构
顺序存储
采用顺序存储方式,则称之为线性表的顺序存储结构,简称为顺序表。
在顺序存储方式下,线性表中的数据元素按照逻辑顺序依次存储在一组连续的存储单元中。
顺序存储的特点如下:
- 表中的数据元素存放在一组连续的存储空间中。
- 数据元素在存储空间中的顺序与它们的逻辑顺序相同。
- 根据数据元素的编号能够计算出它的存储地址。假设第一个元素的地址为ADR(a1),且每个数据元素占S个字节,则第i个数据元素ai的地址为
- ADR(ai)=ADR(a1)+(i-1)*S
- ADR(ai)=ADR(a1)+(i-1)*S
顺序表的主要优点是易于随机存取,可以很方便地访问表中的第i个数据元素。
顺序表的主要缺点是需要一块连续的存储空间,不利于扩充;插入和删除操作需要移动大量的数据元素,效率较低。
适用于读多写少的场景。
链式存储
在链式存储方式下,线性表的数据元素存储在一组任意(连续或者不连续)的存储单元中,用指向数据元素存储位置的指针来表示数据元素之间的逻辑关系。用链式存储结构存储的线性表简称为链表。
为了描述数据元素之间的逻辑关系,存储一个数据元素的时候,还需要存储指针变量,指向它的后继。这两部分合起来称为一个结点,用来表示线性表中的一个数据元素。
这样,链表中的一个结点包含两个域:第一个是数据域,用于存储数据元素;另一个是指针域,用于存储后继元素所在结点的存储位置。通过指针域把所有的结点链接起来,故指针域又被形象地称为链域。
为了能够访问链表中的数据元素,需要有一个访问入口。常常用一个指针变量指向链表中的第一个结点,该指针变量称为头指针H。通过头指针可以找到链表的第一个结点,然后通过各结点指针域找到下一个结点,这样即可访问链表中的所有结点。由于最后一个数据元素没有后继,因此它的结点指针域应为空,用^或者NULL表示。
有时为了操作方便,需在链表的第一个结点之前添加一个伪结点,称为头结点。头结点的数据域可以为空,也可以存放一些控制信息。头结点的指针域存放第一个结点的存储地址。链表的头指针指向头结点,且头指针永不为空。如果链表的长度为0,则头结点的指针域为空。
循环链表
在带头结点的循环链表中,最后一个结点的指针域不再为空,而是指向表头结点。
循环链表的主要特点是从链表中任意结点出发都可以找到表中的所有结点。
双向链表
在单向链表中,可以很方便地访问一个结点的后继。如果要访问一个结点的前驱,则只能从头结点开始向后依次查找每一个结点,效率较低。
为了方便访问结点的前驱,可以给每个结点加上一个指针域,指向它的前驱。这样每个结点就包含两个指针域:一个指向其前驱,一个指向其后继。这样的链表称为双向链表。