线性表
定义和基本操作
具有相同数据类型的 个数据元素的有限序列。
以此我们可以得到以下特性
- 表中元素有限
- 逻辑上元素具有顺序和先后次序
- 所有元素占据的存储空间相同
- 抽象性,仅讨论元素间的逻辑关系,而不必考虑元素表示什么
初始化、表长、按值查找、按位查找、插入、删除、输出、判空、销毁。
广义表
广义表是线性表的一种扩展延伸。相对于线性表,广义表最大的特点在于其元素既可以是一个确定的类型,同时也可以是另一个有不定数量的元素组成的表(广义表)。 不难看出从广义表的定义是递归的。广义表是线性表的递归数据结构。
广义表的两个操作
- :从表头取第一个元素;
- :除去表头之外,由其余元素构成的 广义表。
顺序表示
逻辑上相邻的元素在物理地址上也相邻。
实现上可以使用数组,因此天然地实现了按位查找的操作,其中表长可通过 sizeof
除以单个元素的 size
实现,但是一般来说都是在结构体中直接定义当前长度。
顺序表下标从 开始,而数组中是从 开始的。
顺序表的下标可能表示结构体当中的当前长度,在逻辑上表示表中有多少元素,实际使用时需要减去 .
静态分配:有溢出风险
动态分配:不必为表一次申请所有空间,若占满才申请一块更大的空间
随机存取就是直接存取,可以通过下标直接访问到元素的位置,与存储位置无关;
顺序存取,不能通过下标访问,在存取第 个数据时,必须先访问前 个数据,如链表。
顺序表就属于随机存取。
链式表示
逻辑上相邻的元素在物理地址上不相邻。
每个结点除了存储数据外,还要额外存储一个(或多个)指针,对于单链表,其指针指向后继结点。
通常来说,一般使用一个独立的 头结点
来表示链表,头结点中可以不存放任何信息,也可以记录表长等信息,其指针域指向第一个元素。
对链表第一个位置的处理与其他位置一致;
使空表和非空表的处理得到统一。
双链表
双链表中结点的指针域指向结点的前驱和后继结点,查找较为方便,但是存储空间会稍微大点。
循环链表
即将链表的最后一个结点连接至第一个结点,逻辑上是一个环,但是代码实现中还是需要一个起点。
为了保持一致,空表的头结点指向自身,则其判空条件就是头结点 的前驱后继都指向自己;因此一个单循环列表最末尾结点的指针应该是指向头结点而不是逻辑上的第一个结点。
根据结点指针域的不同,可分为循环单链表和循环双链表。
注意带尾指针循环单链表,其访问后继时间复杂为 ,但是访问前驱的时间复杂度为 ,如删除最后一个元素,由于需要与前驱相连,时间复杂度为 .
静态链表
静态链表借助数组来描述线性表的链式存储结构,每个结点中同样有数据域和指针域,但是这里的指针表示相对地址,又称为 游标
.
静态链表没有但链表使用方便,但是适用于一些没有指针的语言中。