1. 概念
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储
逻辑结构:线性结构
物理结构:顺序存储结构
在内存中是连续存储的:可见:数组就是一种顺序表。
2. 接口实现
2.1. 定义,操作顺序表的,结构体
注意:该结构体不是顺序表本身,而是为了方便操作顺序表而设计
包含:
- 定长数组(即顺序的线性表)
- 数组中,最后个有效元素的下标
#define N 5 // 定长数组大小
typedef int SLDataType; // 顺序表数据类型
// 1. 定义用来操作顺序表的结构体
typedef struct SeqList
{
SLDataType data[N]; // 定长数组
int last; // 数组中最后一个有效元素的下标
} SL;
2.2. 创建空的顺序表
传参注意:传对应地址,而非值传递
2.3. 向 指定的下标位置 插入数据
2.4. 在 指定的下标位置 删除数据
在顺序表中 某个位置插入或删除一个数据元素时,需要耗费时间移动元素。
注意:是人为要求的顺序插入,不可以跳着插入
2.5. 在 指定的下标位置 修改数据
2.6. 遍历打印 顺序表
2.7. 查找指定数据值,第一次出现的下标位置
2.8. 删除表中所有该值的数据(不必要)
3. 总体代码
#include <stdio.h>
#define N 5 // 定长数组大小
typedef int SLDataType; // 顺序表数据类型
// 1. 定义,操作顺序表的,结构体
typedef struct SeqList
{
SLDataType data[N]; // 定长数组
int last; // 数组中最后一个有效元素的下标
} SL;
// 2. 创建空的顺序表
// 注意要传 结构体地址,拒绝值传递
void SLInit(SL *PL)
{
PL->last = -1; //防止出现错误
}
// 3. 向 指定的下标位置 插入数据
// 可插入的下标位置:[0, last+1],得是人为顺序插入
int SLInsert(SL *PL, int post, SLDataType data)
{
// 3.1 容错判断
// 不可在 0下标位置 前
// 可插入当前last身后位置,但不可超过该位置
// 若last已经是末尾位置了,已满,不可再插入
if (post < 0 || post > PL->last + 1 || PL->last == N - 1)
{
printf("SLInsert failed, post not at [0, last+1] or L is full\n");
return -1;
}
// 3.2 插入
// 3.2.1 last后面先移动
// 无需担心post在N-1位置,容错会判断
// post = last,是插入位置就在当前last位置,last后挪即可
// 若是新尾部位置 last < post,不用挪动
for (int i = PL->last; i >= post; i--)
PL->data[i + 1] = PL->data[i];
// 3.2.2 在post上插入数据data
PL->data[post] = data;
// 3.3 最后一个有效元素下标+1
PL->last++;
return 0;
}
// 4. 在 指定的下标位置 删除数据
// 可删除的下标位置:[0, last]
int SLDelete(SL *PL, int post)
{
// 2.1 容错判断
// post < 0,是位置不存在
// post > last 位置不合法,未被用;但可以是 post == last
// last = -1,顺序表无数据
if (post < 0 || post > PL->last || PL->last == -1)
{
printf("SLDelete failed, post not at [0, last] or L is empty\n");
return -1;
}
// 2.2 删除操作
// post = last时,末尾位置值 被覆盖,然后last--
// post < last时,从post开始到last,后面覆盖前面,原last位置被无效数据覆盖,但因长度减1,故无碍
for (int i = post; i <= PL->last; i++)
PL->data[i] = PL->data[i + 1];
// 有效长度 -1
PL->last--;
return 0;
}
// 5. 在 指定的下标位置 修改数据
// 可修改的位置:[0,last]
int SLModify(SL *PL, int post, SLDataType data)
{
// 2.1 容错判断
if (post < 0 || post > PL->last || PL->last == -1)
{
printf("SLModify failed, post not at [0, last] or L is empty\n");
return -1;
}
// 2.2 修改
// 在post上插入数据data
PL->data[post] = data;
return 0;
}
// 6. 遍历打印 顺序表
void SLPrint(SL *PL)
{
for (int i = 0; i <= PL->last; i++)
printf("%d\t", PL->data[i]);
printf("\n");
}
// 7. 查找指定数据值,第一次出现的下标位置
int SLFind(SL *PL, SLDataType data)
{
if (PL->last < 0)
{
printf("SL is Empty!\n");
return -1;
}
// 仅返回第一次找到的下标
for (int i = 0; i <= PL->last; i++)
if (data == PL->data[i])
return i;
return -1;
}
int main(int argc, char *argv[])
{
// 创建顺序表结构体
SL seqlist;
// 初始化空顺序表 结构体
SLInit(&seqlist);
// 依次顺序 插入数据到 顺序表
for (int i = 0; i < N - 1; i++)
SLInsert(&seqlist, i, i * i + 1);
// 打印查看顺序表
SLPrint(&seqlist);
// 修改指定位置数据
SLModify(&seqlist, 2, 999);
// 打印查看顺序表
SLPrint(&seqlist);
// 查找指定数据 所在的位置
printf("post at %d\n", SLFind(&seqlist, 999));
return 0;
}