一. 线性表 定义:
零或多个数据元素组成的优先序列。
数据元素间为一对一关系,每个数据元素a(i)(除头/尾),都有一个前驱a(i-1)和后继a(i+1)
一个数据元素可由多个数据项组成,线性表a(n)长度为n
二. 操作:
查找、插入、删除
三. 线性表的顺序存储
1. 定义: 用一段连续地址依次存储线性表元素。
连续的存储空间需事先声明好,用于存放同类元素;
第i个元素在地址a[i-1]处。
2. 实现: 一维数组 [ArrayList]
3. 操作:
- 查找:
查找i元素,将其存储数组的第i-1位置的值返回即可 - 插入:
数据元素插入第i位,则第i位之后的每位都要依次后移一位方可插入(插入队尾元素除外)
- 删除:
第i位数据删除,则第i位之后的每位都要依次前移一位还原(删除队尾元素除外)
4. 特点:
- 优点:
- 相较于链式存储,无需为元素间的逻辑关系而增加额外的存储空间(指针域)
- 查找快
- 缺点:
- 插入、删除慢,需要移动大量元素
- 线性表的存储空间是固定的,当线性表长度变化较大,难确定存储空间的容量,可能造成空间浪费或不足
四. 线性表的链式存储
1. 定义:
数据域和后继元素存储地址(指针域)组成节点,多节点链接成一个链表。
头结点可以不存储数据,只有指针域指向头指针;
元素与地址位置不具有线性对应关系,可以用一组任意的存储单元存放线性表元素
2. 实现: 单链表[LinkedList]
3. 操作:
- 查找:
从头结点开始查找,直到第i个结点为止,返回其值 - 插入:
让p结点的后继结点 变成s的后继结点,再把结点s变成p的后继结点(顺序不能反)
简述:s指向2,1指向s
代码:s->next=p->next;p->next=s;
- 删除:
让p的后继结点变成s的后继结点,释放s结点
简述:1指向3,释放
代码:p->next=p->next->next
4. 特点: - 优点:
- 插入、删除快
- 不需提前分配存储空间,无数量限制
- 缺点:
- 查找慢
- 指针域分配需占用少量空间,一般可忽略
5. 实现优化:
-
静态链表
定义:用数组描述的链表,元素由数据和指针组成,链表长度固定
特点:在插入和删除操作时,只需要修改游标,不需要移动元素;没有解决连续存储分配带来的表长难以确定的问题。 -
循环链表
定义:将尾结点指针域指向头结点
特点: -
双向链表
定义:设置两个指针域,一个指向前驱结点、一个指向后继结点
五. 特殊线性表
被限定的线性表
1.堆栈
(1)定义: 限定仅在表尾进行插入和删除操作的线性表
把允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素称为空栈。
后进先出的线性表
(2)操作:
- 插入:入栈
- 删除:出栈
(3)实现:顺序栈
- 定义:线性表的特例,通过数组实现
- 操作:进栈 (push)
向栈中压入数据元素,并将栈顶指针上移一位
- 操作:出栈 (pop)
将栈顶数据元素删除,并返回其值 - 特点
- 只在栈顶插入删除元素,不存在线性表的元素移动问题
- 存储空间需要事先确定
(4)优化实现:共享双栈
- 定义:数组有两个端点,两个栈有两个栈底,让一个栈底为数组的始端,即下标0处,另一个栈为栈的末端,即下标n-1处;两个相同元素栈共享存储空间,增加元素就从两端向中间延伸;在原基础上还需有一个参数定义栈号(1/2)
(5)实现:链栈
- **定义:**头指针指向栈顶(无需头节点)
- 操作:进栈
插入结点指向原栈顶元素,头指针改为指向插入结点
- 操作:出栈
将栈顶指针后移一位,释放原栈顶元素
- 特点:
- 无需事先确定存储空间大小
- 增加了指针域的内存开销
(6)栈的应用:递归
-
递归:
把一个直接调用自己或通过一系列的调用语句间接调用自己的函数;
递归函数必须有终止条件;
递归使程序更加清晰简洁,也同时增加了调用函数的副本,消耗时间和内存 -
迭代:
一个函数不断执行循环结构得出结果 -
斐波那契数列
前面相邻两项之和,构成了后一项
[1,1,2,3,5,8,13,21,34,55,89,144,…] -
递归与堆栈
递归的执行包括前进与退回两段正好互为倒序的过程,在实际应用中我们常利用堆栈来实现递归函数中间结果的存储与取出
2.队列
(1)定义:
只允许在一段进行插入操作(队尾),而在另一端进行删除操作(对头)的线性表;
(2)实现:顺序队列
-
定义:
建立一个数组,通过限定/非限定下标对应队列位置的方式进行存储和操作; -
对于限定位置的队列,插入操作在队尾加入元素,元素位置下标对应数组长度,删除需要将第一个元素移除,其他元素全部前移一位;
-
对于非限定位置的队列,不要求元素位置与下标对应,所以可以直接通过删除队头元素、插入队尾元素进行操作;但这样也存在另一种问题,即队列在数组中的位置随着删除操作将产生后移,最终数组下标越界,而还有很多空余空间在数组前面;
(3)优化实现:循环队列 -
定义:队列首尾相连的顺序存储结构;队头和队尾分别用两个指针标识;
-
存在问题:当空队列时 / 队列满时两指针重合,导致无法区分
-
解决方案:
- 设置一个标志变量flag,当front=rear,且flag=0时为队列空;当front=rear,且flag=1时为队列满
- 当队列空时,条件为front=rear,当队列满时,保留一个元素空间。
(4)缺点
空间限制,数组空间溢出问题
(5)实现: 链队列
- 定义: 只能尾进头出的单链表;将队头指针指向头结点,队尾指针指向队尾结点
- 操作:
- 入队:链表尾部插入结点
- 出队:链表头部删除结点
// 注:以上图片及部分内容整理自《大话数据结构》