线性表的相关概念
线性表
- 一、线性表的定义和基本操作
-
- 1.线性表的定义
- 注意:
- 2.线性表的基本操作:
- 二、线性表的顺序表示
-
- 1.顺序表的定义:
- 注意:
- 2.顺序表上基本操作的实现
-
- ①插入操作
- ②删除操作
- ③按值查找
- 三、线性表的链式表示
-
- 1.单链表
- 2.双链表的定义
- 3.循环链表
- 4.静态链表
一、线性表的定义和基本操作 1.线性表的定义 线性表是具有相同数据类型的n(n≥0)个数据元素的有限序列,其中n为表长,当n=0时,该线性表是一个空表。若用L命名线性表,则其一般表示为
L=(a1,a2,a3,.……,an)
式中,a1是唯一的“第一个”数据元素,又称表头元素;an是唯一的“最后一个”数据元素,又称表尾元素。得出线性表的特点如下:
表中元素的个数有限。
表中元素具有逻辑上的顺序性,在序列中各元素排序有其先后顺序。
表中元素都是数据元素,每个元素都是单个元素。
表中元素数据类型都相同,这意味着每个元素占有相同大小的存储空间。
表中元素具有抽象性,即只讨论元素间的逻辑关系,而不考虑元素究竟表示什么内容。
注意: 线性表是一种逻辑结构,表示元素之间一对一的相邻关系。顺序表和链表是指存储结构,两者属于不同层次的概念,因此不要将其混淆。
2.线性表的基本操作:
InitList(&L):初始化表。构造一个空的线性表Length(L):求表长。返回线性表L 的长度,即L中数据元素的个数LocateElem(L.e):按值查找操作。在表L中查找具有给定关键字值的元素GetElem(L,i):按位查找操作。获取表L中第i个位置上的元素的值ListInsert(&L,i,e):插入操作。在表L中第i个位置上插入指定元素eListDelete(&L,i,&e):删除操作。删除表L中第i个位置的元素,并用e返回删除元素的值PrintList(L):输出操作。按前后顺序输出线性表的所有元素值Empty(L):判空操作。若L为空表,则返回true,否则返回falseDestroyList(&L):销毁操作。销毁线性表一并释放线性表L所占用的内存空间
二、线性表的顺序表示 1.顺序表的定义: 线性表的顺序表示又称顺序表。它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。第1个元素存储在线性表的起始位置,第i个元素的存储位置后面紧接着第i+1个元素。因此线性表最大的特点是表中元素的逻辑顺序与其物理顺序相同。
假定线性表的元素类型为ElemType,则线性表的顺序存储结构类型描述为
#define MaxSize 50
typedef struct{
ElemType data[MaxSize];
int length;
}SqList
顺序表最主要的特点是随机访问,即通过首地址和元素序号可在时间O(1)内找到指定的元素。
顺序表的存储密度告,每个结点只存储数据元素。
顺序表逻辑上相邻的元素物理上也相邻,所以插入和删除操作需要移动大量元素。
注意: 线性表中元素的位序是从1开始的,而数组中元素的下标是从0开始的。
2.顺序表上基本操作的实现 ①插入操作
在顺序表的第p个位置插入新元素e。若i的输入不合法,则返回false,表示插入失败;否则将顺序表的第p个元素以及其后的所有元素右移一个位置,腾出一个空位置插入新元素e,顺序表长度增加1,插入成功,返回true。
bool insertElem(Sqlist &L, int p, int e) {
if (p < 0 || p > L.length || L.length == maxSize) {
return false;
}
for (int i = L.length-1;
i >= p;
i--) {
L.data[i+1] = L.data[i];
}
L.data[p] = e;
++(L.length);
return true;
}
最好情况:在表尾插入,元素后移语句将不执行,时间复杂度为O(1);
最坏情况:在表头插入,元素后移语句执行n次,时间复杂度为O(n);
平均情况:在第i个结点插入的概率p为1/(n+1),从1到n+1元素后移语句的执行次数为(n-i+1),等差数列求和得n(n+1)/2,乘以概率p得n/2,因此线性表插入算法的平均时间复杂度为O(n)。
②删除操作
【线性表的相关概念】删除顺序表中第p个位置的元素,若成功返回true,并将被删除的元素用引用变量e返回,否则返回false。
bool deleteElem(Sqlist &L, int p, int &e) {
if (p < 0 || p >= L.length) {
return false;
}
e = L.data[p];
for (int i = p;
i < L.length-1;
i++) {
L.data[i] = L.data[i+1];
}
--(L.length);
return true;
}
最好情况:删除表尾元素,无需移动元素,时间复杂度为O(1);
最坏情况:删除表头元素,需移动除第一个元素外的所有元素,时间复杂度为O(n);
平均情况:删除第i个结点的概率p为1/n,从1到n元素删除后的移动语句的执行次数为(n-i),等差数列求和得n(n-1)/2,乘以概率p得(n-1)/2,因此线性表删除算法的平均时间复杂度为O(n)。
③按值查找
在顺序表中查找第一个元素值等于e的元素,并返回其位序。
int findElem(Sqlist L, int e) {
for (int i = 0;
i < L.length;
i++) {
if (L.data[i] == e) {
return i+1;
}
}
return -1;
}
最好情况:查找的元素在表头,仅需比较一次,时间复杂度为O(1);
最坏情况:查找的元素在表尾或不存在时,需比较n次,时间复杂度为O(n);
平均情况:查找的元素在第i个结点的概率p为1/n,从1到n元素比较次数为i,等差数列求和得n(n+1)/2,乘以概率p得(n+1)/2,因此线性表按值查找算法的平均时间复杂度为O(n)。
三、线性表的链式表示 1.单链表 线性表的链式存储又称单链表,它是指通过一组任意的存储单元来存储线性表中的链式存储。链式存储线性表时,不需要使用地址连续的存储单元,即它不要求逻辑上相邻的两个元素在物理位置上也相邻,它通过“链”建立起数据元素之间的逻辑关系,因此对线性表的插入,删除不需要移动元素,只需要修改指针。
2.双链表的定义 双链表结点中有两个指针prior和next,分别指向其前驱结点和后继结点。
3.循环链表 循环单链表表中的最后一个结点的next指针不是null,而是指向头结点,从而形成一个闭环。
循环双链表表中的头结点的prior指针指向尾结点,尾结点的next指针指向头结点,
4.静态链表
推荐阅读
- 服务/软件管理(10---Linux的网卡(ethtool命令))
- Linux中的计划任务—Crontab调度重复执行的任务
- #yyds干货盘点# Java 基础 - 面向对象的三大特性
- 微软用户:把Win10默认浏览器换成谷歌的
- 盗版系统升级win10后黑屏的处理办法
- Win10自定义高级共享设置的办法
- 聊聊保证线程安全的10个小技巧
- 一种基于生成对抗网络的无人机图像去雾算法
- #yyds干货盘点#Leetcode 26. 删除有序数组中的重复项
- 调用带有 out 参数的方法时检查弃元参数 #yyds干货盘点#