一. 顺序表概念
一言蔽之: 顺序结构的线性表/ 线性表的顺序结构
1. 特点
- 元素集中存储
- 首元素地址, 即顺序表首地址, 亦即底层数组地址
- 基于数组实现
二. 顺序表实现
基于数组实现 ~ (顺序表集中存储的物理结构和数组数据类型完全一致)
struct Table {
int *head;
int len;
int cap;
};
typedef struct Table {
int *head;
int len;
int cap;
} table;
typedef struct {
int *head; //底层动态数组
int len; //长度
int cap; //容量
} Table;
三. 创建顺序表
- 即初始化顺序表
- 底层动态数组初始化
- len + cap 初始化
Table initTab(cap) {
Table tab;
tab.head = malloc(cap * sizeof(int)); //底层动态数组分配内存
tab.len = 0; //长度
tab.cap = cap; //容量
return tab;
}
四. 操作 = 查找 + 修改
查找算法: 顺序查找/ 二分查找/ 插值/ 斐波那契/ etc. 基于时空复杂度择优选择
int getEle(Table tab, int ele) {
for (int i = 0; i < tab.len; ++i) { //查找算法: 顺序查找 etc.
if (tab.head[i] == ele) {
return i;
}
}
return -1;
}
1. 修改元素值: 调用查找算法定位并修改
Table updateEle(Table tab, int ele, int newEle) {
tab.head[getEle(tab, ele)] = newEle; //修改元素值
return tab;
}
2. 修改表结构(增/ 删元素)
- 表头插入
- 中间
- 尾追加
Table insertEle(Table tab, int i, int ele) {
for (int j = tab.len - 1; j >= i; j--) { //元素移民
tab.head[j + 1] = tab.head[j];
}
tab.head[i] = ele; //插入
tab.len++;
return tab;
}
- 表头删除
- 中间
- 表尾
Table delEle(Table tab, int ele) {
for (int i = getEle(tab, ele) + 1; i < tab.len; ++i) { //覆盖删除
tab.head[i - 1] = tab.head[i];
}
tab.len--;
return tab;
/*
覆盖删除
1. 元素从顺序表而不是底层数组删除, 通过底层数组仍可访问
*/
}
六. 完整程序
代码
#include <stdio.h>
#include <stdlib.h>
//顺序表物理结构
typedef struct {
int *head; //底层动态数组
int len; //长度
int cap; //容量
} Table;
//初始化顺序表
Table initTab(int cap) {
Table tab;
tab.head = malloc(cap * sizeof(int)); //底层动态数组分配内存
if (!tab.head) {
printf("底层数组初始化失败!\n");
/*
可能因素
1. 申请内存过大
*/
} else {
tab.len = 0; //长度
tab.cap = cap; //容量
}
return tab;
}
/*
操作
1. 查找
2. 修改
1. 修改元素值
2. 修改表结构
1. 插入元素
2. 删除元素
*/
//1. 查找
int getEle(Table tab, int ele) {
for (int i = 0; i < tab.len; i++) { //查找算法: 顺序查找 etc.
if (tab.head[i] == ele) {
return i;
}
}
return -1;
}
//2.1 修改/ 更新元素值
Table updateEle(Table tab, int ele, int newEle) {
int i = getEle(tab, ele);
if (i == -1) {
printf("元素 %d 不存在\n", ele);
return tab;
}
tab.head[i] = newEle; //更新
return tab;
}
//2.2.1 插入元素
Table insertEle(Table tab, int i, int ele) {
if (i < 0 || tab.len < i) {
printf("插入元素索引%d异常\n", i);
return tab;
} else if (tab.cap <= i) {
tab.head = realloc(tab.head, (tab.cap + 2) * sizeof(int)); //扩容算法
if (!tab.head) {
printf("底层数组扩容失败!\n");
return tab;
}
tab.cap *= 2;
}
for (int j = tab.len; j > i; j--) { //元素移民
tab.head[j] = tab.head[j - 1];
}
tab.head[i] = ele; //插入
tab.len++;
return tab;
}
//2.2.2 删除元素
Table delEle(Table tab, int ele) {
int i = getEle(tab, ele);
if (i == -1) {
printf("待删除元素 %d 不存在\n", ele);
return tab;
}
for (int j = i; j < tab.len - 1; j++) { //元素移民: 覆盖删除
tab.head[j] = tab.head[j + 1];
}
tab.len--;
return tab;
}
测试
void day02() {
Table tab = initTab(10);
for (int i = 0; i < tab.cap; ++i) {
tab = insertEle(tab, i, i+1);
}
/*查找元素
printf("%d\n", getEle(tab, -1));
printf("%d\n", getEle(tab, 3));
printf("%d\n", getEle(tab, 11));*/
/*修改/ 更新元素值
tab = updateEle(tab, 222, 2);
tab = updateEle(tab, 2, 222);*/
/*插入元素
tab = insertEle(tab, -1, 11);
tab = insertEle(tab, 0, 22);
tab = insertEle(tab, 3, 33);
tab = insertEle(tab, 9, 44);
tab = insertEle(tab, tab.len, 55);*/
/*tab = delEle(tab, -1);
tab = delEle(tab, 0);
tab = delEle(tab, 4);
tab = delEle(tab, 10);
tab = delEle(tab, 11);*/
for (int i = 0; i < tab.len; ++i) {
printf("tab[%d] = %d\n", i, tab.head[i]);
}
}