在正式介绍顺序表之前,我们有必要先了解一个名词:线性表。
线性表:
线性表是,具有n个相同特性的数据元素的有限序列。常见的线性表:顺序表、链表、栈、队列、数组、字符串...
线性表在逻辑上是线性结构,但在物理结构上并不一定是连续的。
1. 顺序表概念
顺序表是用一段物理地址连续的储存单元、依次存储数据元素的线性结构,一般情况下采用数组存储。
2. 顺序表定义
typedef int SLDataType;// 顺序表数据类型
typedef struct SeqList
{
SLDataType* arr; // 指向动态开辟的数组
int size; // 有效数据个数
int capacity; // 容量
}SL;
3. 顺序表的初始化
顺序表的初始化,是使用 动态内存管理 开辟空间构造一个空的顺序表
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define DefaultCapacity 4 // 默认初始化空间大小
void SLInit(SL* ps)
{
assert(ps);
SLDataType* tmp = (SLDataType*)malloc(sizeof(SLDataType) * DefaultCapacity);
if (tmp == NULL)
{
perror("malloc");
exit(-1);
}
ps->arr = tmp;
ps->capacity = DefaultCapacity;
ps->size = 0;
}
4. 在pos位置插入元素
在pos位置插入数据之前,要检查动态顺序表的容量是否足够 ,
不够则利用 realloc函数 开辟一块更大的空间给顺序表。
检查容量/扩容:
void SLCapacityCheck(SL* ps)
{
assert(ps);
if (ps->size == ps->capacity)
{
SLDataType* tmp = (SLDataType*)realloc(ps->arr, ps->capacity * 2 * sizeof(SLDataType));
if (tmp == NULL)
{
perror("realloc");
exit(-1);
}
ps->capacity *= 2;
ps->arr = tmp;
}
}
插入:
void SLInsert(SL* ps, int pos, SLDataType x)
{
assert(ps);
SLCapacityCheck(ps);
for (int i = ps->size - 1; i >= pos; i--)
{
ps->arr[i + 1] = ps->arr[i];
}
ps->arr[pos] = x;
ps->size++;
}
5. 删除pos位置元素
void SLErase(SL* ps, int pos)
{
assert(ps);
for (int i = pos + 1; i < ps->size; i++)
{
ps->arr[i - 1] = ps->arr[i];
}
ps->size--;
}
6. 顺序表查找(按值查找)
int SLFind(SL* ps, SLDataType x)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
if (ps->arr[i] == x)
return i;
}
// 找不到所查找的元素
return -1;
}
在主函数中使用 SLFind函数 时,应检验 “返回值” 是否为非 -1,再使用
7. 顺序表的打印
void SLPrint(SL* ps)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->arr[i]);
}
printf("\n");
}
8. 顺序表销毁
void SLDestroy(SL* ps)
{
assert(ps);
free(ps->arr);
ps->capacity = 0;
ps->size = 0;
}
销毁 arr 所指向的空间,将空间还给操作系统。