线性表的定义
- 零个或多个数据元素的有限序列
分类
- 顺序储存结构
- 链式储存结构
- 单链表
- 静态链表
- 循环链表
- 双向链表
顺序储存结构
- 宏定义
|
|
- 结构体
|
|
获得元素
|
|
插入元素
算法思路:
- 如果插入位置不合理,抛出异常
- 如果线性表长度大于等于数组长度,则抛出异常或者动态扩容
- 从最后一个元素开始向前遍历到第i的位置,分别将他们向后移动一个位置
- 将要插入的元素填入到位置i处
- 表长 + 1
|
|
删除操作
算法思路
- 如果删除的位置不合理,抛出异常
- 去出删除的元素
- 从删除的元素开始遍历到最后一个元素,分别将他们都向前移动一个位置
*表长 - 1
|
|
时间复杂度
- 最好情况下,如果插入的元素是最后一个,或者删除的元素是最后一个,意味着元素不用移动,那么时间复杂度为O(1)。
- 最坏情况,如果插入的元素在第一个,或者删除的元素在第一个,那么意味着全部元素将要向前或者向后移动,时间复杂度为O(n)。
- 平均情况: 时间复杂度为O(n)
优点
- 快速存取表中的任一元素
缺点
- 插入和删除需要大量移动元素
- 当线性表长度变化较大时,难以确定储存空间
链式储存结构
- 结构体
|
|
单链表的读取
算法思路
- 声明一个指针p指向链表第一个结点,初始化j从1开始
- 当j<i时,就遍历链表,让p的指针向后移动,不断指向下一个结点,j累加1
- 若到链表末尾p为空,则说明第i个结点不存在
- 否则查找成功,返回结点p的数据
|
|
单链表的插入
算法思路:
- 声明一指针指向链表头结点,初始化j从1开始
- 当j<i时,遍历链表,让p的指针向后移动,不断指向下一个结点,j累加1
- 若到链表末尾为空,则说明第i的结点不存在
- 否则查找成功,在系统中生成一个空的结点s
- 将数据元素e赋值给s->data
- 进行单链表插入操作
|
|
单链表的删除
算法思路
- 声明一指针指向链表头结点,初始化j从1开始
- 当j<i时,遍历链表,让p的指针向后移动,不断指向下一个结点,j累加1
- 若到链表末尾为空,则说明第i的结点不存在
- 若查找成功,将欲删除的结点p->next赋值给q
- 删除结点
- 将q结点中的数据赋值给e并返回
- 释放q结点
- 返回成功
|
|
创建单链表
算法思路
- 声明一指针p和计数器变量i
- 初始化空链表L
- 让空链表的头结点指向NULL,即建立头结点
- 循环创建结点
- 头插法
|
|
- 尾插法
|
|
单链表的整体删除
算法思路
- 声明一个结点p和q
- 将第一个结点赋值给p
- 循环
- 将下一个结点赋值给q
- 释放q
- 将q赋值给p
|
|
比较
储存方式
- 顺序储存结构用一端连续的储存单元储存元素
- 单链表用链式储存元素
时间性能
查找
- 顺序结构:O(1)
- 链式储存结构O(n)
插入和删除
- 顺序储存结构需要平均移动毕表长的一半,时间为O(n)
- 单链表在线出某个位置指针后,插入和删除为O(1)
空间性能
- 顺序结构需要预分配储存空间,分大了浪费,分小了溢出
- 单链表可以实时分配空间
静态链表
- 用数组描述的链表,是为了解决一个语言中没有指针的问题
- 结构体
|
|
- 通常把未被使用的数组称为备用链表
- 数组的第一个元素的cur存放备用链表的第一个结点下标
- 数组最后一个元素的cur存放第一个元素的下标,相当与头结点
- 初始化:
|
|
删除操作
|
|
插入操作
|
|
优点
- 在插入和删除元素时,只需移动修改下标,从而改进顺序储存结构中插入和删除元素需要大量移动元素的缺点
缺点
- 没有解决难以确定表长的缺点
- 失去了顺序储存结构中随机存取元素的特性
以上笔记来源《大话数据结构》中
源码