一、视频讲解
- 抽象数据类型:https://www.bilibili.com/video/BV19V411m7MB
- 顺序存储及定义:https://www.bilibili.com/video/BV1t54y1k729
- 顺序存储实现·上:https://www.bilibili.com/video/BV1FK4y1h7rZ
- 顺序存储实现·下:https://www.bilibili.com/video/BV1cV411278T
二、对应博客(勿记笔记)
- 系列博客:http://www.nowamagic.net/librarys/veda/detail/2198
- 和视频配套,疑似一人所做
三、抽象数据类型线性表的基本操作
-
初始化线性表
InitList(&L)
构造一个空的线性表
L
(1)为线性表申请内存空间 (2)length成员设置为0 void InitList(SqList* &list){ list = (sqList *)malloc(sizeof(SqList)); list->length = 0; }
# include <stdio.h> # include <stdlib.h> typedef int ElemType; # define MaxSize 100 typedef struct{ ElemType datas[MaxSize]; int length; }SqList; void InitList(SqList* &L); int main() { // 初始化结构体 SqList *p; // 初始化线性表 InitList(p); // 输出测试 printf("%d",p->length); return 0; } // 初始化线性表 /*指针的引用:int *&a = p;其中p本身就是指针,所以a和p其实是指向同一块地址的*/ void InitList(SqList* &L) { // 动态分配 L = (SqList *)malloc(sizeof(SqList)); L->length = 0; }
-
顺序表的创建
CreateList
运算的结果是构造一个含有
n
个数据元素的线性表(1)为线性表申请内存空间 (2)逐个将数组中的元素读取到线性表的data数组成员中 (3)设置线性表的长度,length成员赋值
# include <stdio.h> # include <stdlib.h> typedef int ElemType; # define MaxSize 100 typedef struct { ElemType datas[MaxSize]; int length; } SqList; // 函数的声明 void InitList(SqList *L); void CreateList(SqList *L,ElemType a[],int n); int main() { // 初始化结构体 SqList L; InitList(&L); // 需要初始化数组 int a[] = {3,4,7,8,1,2,5,6,0}; // 计算数组的长度 int n = sizeof(a) / sizeof(a[0]); CreateList(&L,a,n); printf("线性表的长度为:%d",L.length); return 0; } // 线性表的初始化 void InitList(SqList *L){ L = (SqList *)malloc(sizeof(SqList)); L->length = 0; } // 顺序表的创建 void CreateList(SqList *L,ElemType a[],int n){ int i; // 因为在InitList中已经申请了内存空间了,所以这步可以省去 for(i = 0;i < n && i < MaxSize;i++){ L->datas[i] = a[i]; L->length += 1; } }
注意:
CreateList
内部循环条件的判断同样要求要小于线性表初始化时数组的长度 -
判断线性表是否为空表
ListEmpty(L)
若为空表
length == 0
,则返回真,否则返回假# include <stdio.h> # include <stdlib.h> typedef int ElemType; # define MaxSize 100 typedef struct { ElemType datas[MaxSize]; int length; } SqList; // 函数的声明 void InitList(SqList *L); void CreateList(SqList *L,ElemType a[],int n); bool ListEmpty(SqList *L); int main() { // 初始化结构体 SqList L; InitList(&L); // 需要初始化数组 int a[] = {3,4,7,8,1,2,5,6,0}; // 计算数组的长度 int n = sizeof(a) / sizeof(a[0]); CreateList(&L,a,n); printf("线性表是否是空表:%d",ListEmpty(&L)); return 0; } // 线性表的初始化 void InitList(SqList *L){ L = (SqList *)malloc(sizeof(SqList)); L->length = 0; } // 顺序表的创建 void CreateList(SqList *L,ElemType a[],int n){ int i; // 因为在InitList中已经申请了内存空间了,所以这步可以省去 for(i = 0;i < n && i < MaxSize;i++){ L->datas[i] = a[i]; L->length += 1; } } // 线性表的判空 bool ListEmpty(SqList *L){ // length == 0则返回真,否则返回假 return (L->length == 0); }
-
求线性表的长度
ListLength(L)
返回
L
中元素的个数n
# include <stdio.h> # include <stdlib.h> typedef int ElemType; # define MaxSize 100 typedef struct { ElemType datas[MaxSize]; int length; } SqList; // 函数的声明 void InitList(SqList *L); void CreateList(SqList *L,ElemType a[],int n); bool ListEmpty(SqList *L); void DispList(SqList *L); int ListLength(SqList *L); int main() { // 初始化结构体 SqList L; InitList(&L); // 需要初始化数组 int a[] = {3,4,7,8,1,2,5,6,0}; // 计算数组的长度 int n = sizeof(a) / sizeof(a[0]); CreateList(&L,a,n); DispList(&L); printf("%d",ListLength(&L)); return 0; } // 线性表的初始化 void InitList(SqList *L){ L = (SqList *)malloc(sizeof(SqList)); L->length = 0; } // 顺序表的创建 void CreateList(SqList *L,ElemType a[],int n){ int i; // 因为在InitList中已经申请了内存空间了,所以这步可以省去 for(i = 0;i < n && i < MaxSize;i++){ L->datas[i] = a[i]; L->length += 1; } } // 线性表的判空 bool ListEmpty(SqList *L){ // length == 0则返回真,否则返回假 return (L->length == 0); } // 输出线性表 void DispList(SqList *L){ int i; // 当线性表是空时,不输出显示 if (ListEmpty(L)) return; else{ for(i = 0;i < L->length;i++) { printf("%d\t",L->datas[i]); } printf("\n"); } } // 返回线性表的表长 int ListLength(SqList *L){ return L->length; }
-
输出线性表
DispList(L)
线性表
L
不为空时,顺序显示各结点的值# include <stdio.h> # include <stdlib.h> typedef int ElemType; # define MaxSize 100 typedef struct { ElemType datas[MaxSize]; int length; } SqList; // 函数的声明 void InitList(SqList *L); void CreateList(SqList *L,ElemType a[],int n); bool ListEmpty(SqList *L); void DispList(SqList *L); int main() { // 初始化结构体 SqList L; InitList(&L); // 需要初始化数组 int a[] = {3,4,7,8,1,2,5,6,0}; // 计算数组的长度 int n = sizeof(a) / sizeof(a[0]); CreateList(&L,a,n); DispList(&L); return 0; } // 线性表的初始化 void InitList(SqList *L){ L = (SqList *)malloc(sizeof(SqList)); L->length = 0; } // 顺序表的创建 void CreateList(SqList *L,ElemType a[],int n){ int i; // 因为在InitList中已经申请了内存空间了,所以这步可以省去 for(i = 0;i < n && i < MaxSize;i++){ L->datas[i] = a[i]; L->length += 1; } } // 线性表的判空 bool ListEmpty(SqList *L){ // length == 0则返回真,否则返回假 return (L->length == 0); } // 输出线性表 void DispList(SqList *L){ int i; // 当线性表是空时,不输出显示 if (ListEmpty(L)) return; else{ for(i = 0;i < L->length;i++) { printf("%d\t",L->datas[i]); } printf("\n"); } }
-
求线性表
L
中指定位置的某个数据元素GetElem(L,i,&e)
用
e
返回L
中第i(1≤i≤n)
个元素的值(1)操作成功的话值为true,否则为false (2)长度为0或者超出最大的范围(大于length),返回false
# include <stdio.h> # include <stdlib.h> typedef int ElemType; # define MaxSize 100 typedef struct { ElemType datas[MaxSize]; int length; } SqList; // 函数的声明 void InitList(SqList *L); void CreateList(SqList *L,ElemType a[],int n); bool ListEmpty(SqList *L); void DispList(SqList *L); int ListLength(SqList *L); bool GetElem(SqList *L,int i,ElemType &e); int main() { // 初始化结构体 SqList L; InitList(&L); // 需要初始化数组 int a[] = {3,4,7,8,1,2,5,6,0}; // 计算数组的长度 int n = sizeof(a) / sizeof(a[0]); CreateList(&L,a,n); DispList(&L); // 操作成功则输出获取的元素的值 ElemType m; int i = 2; if(GetElem(&L,i,m)){ printf("获取到的第%d个元素是:%d",i,m); } return 0; } // 线性表的初始化 void InitList(SqList *L){ L = (SqList *)malloc(sizeof(SqList)); L->length = 0; } // 顺序表的创建 void CreateList(SqList *L,ElemType a[],int n){ int i; // 因为在InitList中已经申请了内存空间了,所以这步可以省去 for(i = 0;i < n && i < MaxSize;i++){ L->datas[i] = a[i]; L->length += 1; } } // 线性表的判空 bool ListEmpty(SqList *L){ // length == 0则返回真,否则返回假 return (L->length == 0); } // 输出线性表 void DispList(SqList *L){ int i; // 当线性表是空时,不输出显示 if (ListEmpty(L)) return; else{ for(i = 0;i < L->length;i++) { printf("%d\t",L->datas[i]); } printf("\n"); } } // 返回线性表的表长 int ListLength(SqList *L){ return L->length; } // 获取线性表某位置的元素 bool GetElem(SqList *L,int i,ElemType &e){ if(i < 1 || i > L->length) return false; else{ e = L->datas[i-1]; return true; } }
-
定位查找
LocateElem(L,e)
返回
L
中第一个值与e
相等的逻辑位序,若这样的元素不存在则返回值0算法步骤: (1)循环变量i初始化为0 (2)比较下标i所指向的数据是否与e相等,如果相等则找到了,返回i+1,否则循环变量自增1 (3)判断是否扫描完所有的数据元素,若没有则返回(2),否则到下一步 (4)返回0
# include <stdio.h> # include <stdlib.h> typedef int ElemType; # define MaxSize 100 typedef struct { ElemType datas[MaxSize]; int length; } SqList; // 函数的声明 void InitList(SqList *L); void CreateList(SqList *L,ElemType a[],int n); bool ListEmpty(SqList *L); void DispList(SqList *L); int ListLength(SqList *L); bool GetElem(SqList *L,int i,ElemType &e); int LocateElem(SqList *L,ElemType e); int main() { // 初始化结构体 SqList L; InitList(&L); // 需要初始化数组 int a[] = {3,4,7,8,1,2,5,6,0}; // 计算数组的长度 int n = sizeof(a) / sizeof(a[0]); CreateList(&L,a,n); DispList(&L); // 操作成功则输出获取的元素的值 ElemType m; int i = 2; if(GetElem(&L,i,m)){ printf("获取到的第%d个元素是:%d\n",i,m); } // 寻找6在线性表中是第几个元素 int find_value = 6; if(LocateElem(&L,find_value)){ printf("%d在线性表中是第%d个元素\n",find_value,LocateElem(&L,find_value)); } return 0; } // 线性表的初始化 void InitList(SqList *L){ L = (SqList *)malloc(sizeof(SqList)); L->length = 0; } // 顺序表的创建 void CreateList(SqList *L,ElemType a[],int n){ int i; // 因为在InitList中已经申请了内存空间了,所以这步可以省去 for(i = 0;i < n && i < MaxSize;i++){ L->datas[i] = a[i]; L->length += 1; } } // 线性表的判空 bool ListEmpty(SqList *L){ // length == 0则返回真,否则返回假 return (L->length == 0); } // 输出线性表 void DispList(SqList *L){ int i; // 当线性表是空时,不输出显示 if (ListEmpty(L)) return; else{ for(i = 0;i < L->length;i++) { printf("%d\t",L->datas[i]); } printf("\n"); } } // 返回线性表的表长 int ListLength(SqList *L){ return L->length; } // 获取线性表某位置的元素 bool GetElem(SqList *L,int i,ElemType &e){ if(i < 1 || i > L->length) return false; else{ e = L->datas[i-1]; return true; } } // 定位某个值在线性表中的位置 int LocateElem(SqList *L,ElemType e){ int i; for(i = 0;i < L->length;i++){ if(L->datas[i] == e){ return (i + 1); } } // 没有找到就返回0 return 0; }
-
插入一个数据元素
ListInsert(&L,i,e)
在
L
的第i(1≤i≤n)
个元素之前插入新的元素e
,L
的长度增1算法步骤: (1)判断插入的位置i是否合法,不合法则返回false,合法则到下一步 (2)判断顺序表的存储空间是否已满,满了则返回false,否则进入下一步 (3)将从最后一个到第i个元素依次向后移动一个位置,空出第i个位置 (4)将e赋值为下标为i的数据项 (5)线性表的长度+1 (6)插入成功返回true 时间复杂度: 元素移动和表长L->length=n有关,也与插入位置i有关 - 当i = n + 1时,移动次数为0,算法最好时间复杂度为O(1) - 当i = 1时,移动次数为n,达到最大值,苏纳法最坏时间复杂度为O(n)
# include <stdio.h> # include <stdlib.h> typedef int ElemType; # define MaxSize 100 typedef struct { ElemType datas[MaxSize]; int length; } SqList; // 函数的声明 void InitList(SqList *L); void CreateList(SqList *L,ElemType a[],int n); bool ListEmpty(SqList *L); void DispList(SqList *L); int ListLength(SqList *L); bool GetElem(SqList *L,int i,ElemType &e); int LocateElem(SqList *L,ElemType e); bool ListInsert(SqList *L,int i,ElemType e); int main() { // 初始化结构体 SqList L; InitList(&L); // 需要初始化数组 int a[] = {3,4,7,8,1,2,5,6,0}; // 计算数组的长度 int n = sizeof(a) / sizeof(a[0]); CreateList(&L,a,n); DispList(&L); // 操作成功则输出获取的元素的值 ElemType m; int i = 2; if(GetElem(&L,i,m)){ printf("获取到的第%d个元素是:%d\n",i,m); } // 寻找6在线性表中是第几个元素 int find_value = 6; if(LocateElem(&L,find_value)){ printf("%d在线性表中是第%d个元素\n",find_value,LocateElem(&L,find_value)); } // 开始插入元素 int insert_value = 10; int insert_location = 3; if(ListInsert(&L,insert_location,insert_value)){ // 输出线性表进行对比 printf("向第%d个位置插入元素%d后:\n",insert_location,insert_value); DispList(&L); } return 0; } // 线性表的初始化 void InitList(SqList *L){ L = (SqList *)malloc(sizeof(SqList)); L->length = 0; } // 顺序表的创建 void CreateList(SqList *L,ElemType a[],int n){ int i; // 因为在InitList中已经申请了内存空间了,所以这步可以省去 for(i = 0;i < n && i < MaxSize;i++){ L->datas[i] = a[i]; L->length += 1; } } // 线性表的判空 bool ListEmpty(SqList *L){ // length == 0则返回真,否则返回假 return (L->length == 0); } // 输出线性表 void DispList(SqList *L){ int i; // 当线性表是空时,不输出显示 if (ListEmpty(L)) return; else{ for(i = 0;i < L->length;i++) { printf("%d\t",L->datas[i]); } printf("\n"); } } // 返回线性表的表长 int ListLength(SqList *L){ return L->length; } // 获取线性表某位置的元素 bool GetElem(SqList *L,int i,ElemType &e){ if(i < 1 || i > L->length) return false; else{ e = L->datas[i-1]; return true; } } // 定位某个值在线性表中的位置 int LocateElem(SqList *L,ElemType e){ int i; for(i = 0;i < L->length;i++){ if(L->datas[i] == e){ return (i + 1); } } // 没有找到就返回0 return 0; } // 向线性表某位置插入元素 bool ListInsert(SqList *L,int i,ElemType e){ if(i > L->length + 1 || i < 1) return false; else{ // 逻辑位序转换为物理位序 i -= 1; int j; for(j = L->length;j > i;j--) { // 依次向后移 L->datas[j] = L->datas[j-1]; } L->datas[i] = e; L->length += 1; } return true; }
-
线性表元素删除操作
ListDelete(&L,i,&e)
删除线性表的某个元素
算法步骤: (1)判断删除位置i是否合法,不合法则返回false,合法则到下一步 (2)将要删除的元素保存到输出参数e中 (3)从第i+1个元素到最后一个元素,顺序前移一个位置 (4)线性表长度减1 (5)删除成功,返回true 时间复杂度情况和插入几乎一致
# include <stdio.h> # include <stdlib.h> typedef int ElemType; # define MaxSize 100 typedef struct { ElemType datas[MaxSize]; int length; } SqList; // 函数的声明 void InitList(SqList *L); void CreateList(SqList *L,ElemType a[],int n); bool ListEmpty(SqList *L); void DispList(SqList *L); int ListLength(SqList *L); bool GetElem(SqList *L,int i,ElemType &e); int LocateElem(SqList *L,ElemType e); bool ListInsert(SqList *L,int i,ElemType e); bool ListDelete(SqList *L,int i,ElemType &e); int main() { // 初始化结构体 SqList L; InitList(&L); // 需要初始化数组 int a[] = {3,4,7,8,1,2,5,6,0}; // 计算数组的长度 int n = sizeof(a) / sizeof(a[0]); CreateList(&L,a,n); DispList(&L); // 操作成功则输出获取的元素的值 ElemType m; int i = 2; if(GetElem(&L,i,m)){ printf("获取到的第%d个元素是:%d\n",i,m); } // 寻找6在线性表中是第几个元素 int find_value = 6; if(LocateElem(&L,find_value)){ printf("%d在线性表中是第%d个元素\n",find_value,LocateElem(&L,find_value)); } // 开始插入元素 int insert_value = 10; int insert_location = 3; if(ListInsert(&L,insert_location,insert_value)){ // 输出线性表进行对比 printf("向第%d个位置插入元素%d后:\n",insert_location,insert_value); DispList(&L); } // 开始删除元素 int delete_location = 4; if(ListDelete(&L,delete_location,m)){ // 确实操作成功了,直接显示线性表 printf("删除第%d号元素%d后:\n",delete_location,m); DispList(&L); } return 0; } // 线性表的初始化 void InitList(SqList *L){ L = (SqList *)malloc(sizeof(SqList)); L->length = 0; } // 顺序表的创建 void CreateList(SqList *L,ElemType a[],int n){ int i; // 因为在InitList中已经申请了内存空间了,所以这步可以省去 for(i = 0;i < n && i < MaxSize;i++){ L->datas[i] = a[i]; L->length += 1; } } // 线性表的判空 bool ListEmpty(SqList *L){ // length == 0则返回真,否则返回假 return (L->length == 0); } // 输出线性表 void DispList(SqList *L){ int i; // 当线性表是空时,不输出显示 if (ListEmpty(L)) return; else{ for(i = 0;i < L->length;i++) { printf("%d\t",L->datas[i]); } printf("\n"); } } // 返回线性表的表长 int ListLength(SqList *L){ return L->length; } // 获取线性表某位置的元素 bool GetElem(SqList *L,int i,ElemType &e){ if(i < 1 || i > L->length) return false; else{ e = L->datas[i-1]; return true; } } // 定位某个值在线性表中的位置 int LocateElem(SqList *L,ElemType e){ int i; for(i = 0;i < L->length;i++){ if(L->datas[i] == e){ return (i + 1); } } // 没有找到就返回0 return 0; } // 向线性表某位置插入元素 bool ListInsert(SqList *L,int i,ElemType e){ if(i > L->length + 1 || i < 1) return false; else{ // 逻辑位序转换为物理位序 i -= 1; int j; for(j = L->length;j > i;j--) { // 依次向后移 L->datas[j] = L->datas[j-1]; } L->datas[i] = e; L->length += 1; } return true; } // 删除线性表中第i个位置的元素 bool ListDelete(SqList *L,int i,ElemType &e){ if(i < 1 || i > L->length) return false; else{ // 逻辑位序转化为物理位序 i -= 1; int j; e = L->datas[i]; for(j = i;j < L->length;j++){ // 依次往前推 L->datas[i] = L->datas[i+1]; } L->length -= 1; return true; } }
-
线性表的销毁
DestroyList(& L)
释放线性表占用的内存空间,仅执行释放线性表所占内存空间的操作
# include <stdio.h> # include <stdlib.h> typedef int ElemType; # define MaxSize 100 typedef struct { ElemType datas[MaxSize]; int length; } SqList; // 函数的声明 void InitList(SqList *L); void CreateList(SqList *L,ElemType a[],int n); bool ListEmpty(SqList *L); void DispList(SqList *L); int ListLength(SqList *L); bool GetElem(SqList *L,int i,ElemType &e); int LocateElem(SqList *L,ElemType e); bool ListInsert(SqList *L,int i,ElemType e); bool ListDelete(SqList *L,int i,ElemType &e); void DestroyList(SqList *L); int main() { // 初始化结构体 SqList L; InitList(&L); // 需要初始化数组 int a[] = {3,4,7,8,1,2,5,6,0}; // 计算数组的长度 int n = sizeof(a) / sizeof(a[0]); CreateList(&L,a,n); DispList(&L); // 操作成功则输出获取的元素的值 ElemType m; int i = 2; if(GetElem(&L,i,m)){ printf("获取到的第%d个元素是:%d\n",i,m); } // 寻找6在线性表中是第几个元素 int find_value = 6; if(LocateElem(&L,find_value)){ printf("%d在线性表中是第%d个元素\n",find_value,LocateElem(&L,find_value)); } // 开始插入元素 int insert_value = 10; int insert_location = 3; if(ListInsert(&L,insert_location,insert_value)){ // 输出线性表进行对比 printf("向第%d个位置插入元素%d后:\n",insert_location,insert_value); DispList(&L); } // 开始删除元素 int delete_location = 4; if(ListDelete(&L,delete_location,m)){ // 确实操作成功了,直接显示线性表 printf("删除第%d号元素%d后:\n",delete_location,m); DispList(&L); } // 销毁线性表 DestroyList(&L); return 0; } // 线性表的初始化 void InitList(SqList *L){ L = (SqList *)malloc(sizeof(SqList)); L->length = 0; } // 顺序表的创建 void CreateList(SqList *L,ElemType a[],int n){ int i; // 因为在InitList中已经申请了内存空间了,所以这步可以省去 for(i = 0;i < n && i < MaxSize;i++){ L->datas[i] = a[i]; L->length += 1; } } // 线性表的判空 bool ListEmpty(SqList *L){ // length == 0则返回真,否则返回假 return (L->length == 0); } // 输出线性表 void DispList(SqList *L){ int i; // 当线性表是空时,不输出显示 if (ListEmpty(L)) return; else{ for(i = 0;i < L->length;i++) { printf("%d\t",L->datas[i]); } printf("\n"); } } // 返回线性表的表长 int ListLength(SqList *L){ return L->length; } // 获取线性表某位置的元素 bool GetElem(SqList *L,int i,ElemType &e){ if(i < 1 || i > L->length) return false; else{ e = L->datas[i-1]; return true; } } // 定位某个值在线性表中的位置 int LocateElem(SqList *L,ElemType e){ int i; for(i = 0;i < L->length;i++){ if(L->datas[i] == e){ return (i + 1); } } // 没有找到就返回0 return 0; } // 向线性表某位置插入元素 bool ListInsert(SqList *L,int i,ElemType e){ if(i > L->length + 1 || i < 1) return false; else{ // 逻辑位序转换为物理位序 i -= 1; int j; for(j = L->length;j > i;j--) { // 依次向后移 L->datas[j] = L->datas[j-1]; } L->datas[i] = e; L->length += 1; } return true; } // 删除线性表中第i个位置的元素 bool ListDelete(SqList *L,int i,ElemType &e){ if(i < 1 || i > L->length) return false; else{ // 逻辑位序转化为物理位序 i -= 1; int j; e = L->datas[i]; for(j = i;j < L->length;j++){ // 依次往前推 L->datas[i] = L->datas[i+1]; } L->length -= 1; return true; } } // 销毁线性表 void DestroyList(SqList *L){ free(L); L = NULL; }