文章目录
前言
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存
储。在数组上完成数据的增删查改。
一、顺序表的两种常用类型:
1.1顺序表的静态定义
#define N 7
typedef int SLDataType;//SL为Sequence List的缩写也就是顺序表
//定义顺序表的类型方便后续的修改
typedef struct SL {
SLDataType array[N];//定长数组不可修改数值
int size;//当前数组中所放的的有效数据
};
1.2顺序表的动态定义
typedef int SLDataType;//SL为Sequence List的缩写也就是顺序表
//定义顺序表的类型方便后续的修改
typedef struct SL {//动态表比较灵活可进行扩容
SLDataType* a;//指向顺序开辟的数组
int size;//当前的有效数据
int capacity;//数组的最大容量
}SL;
二、顺序表的功能
2.1顺序表的初始化(SLInit)
#define INIT_SZ 4//初始的顺序表容积的大小
void SLInit(SL* ps) {
assert(ps);//检查ps是否为空
ps->a = (SLDataType*)malloc(sizeof(SLDataType) * INIT_SZ);
if (ps->a == NULL) {//判断申请的内存是否有意义
perror("SLInit");//无意义在打印错误原因
return;
}
ps->size = 0;//刚开始有效数据为0
ps->capacity = INIT_SZ;//初始化容积
}
2.2顺序表的销毁操作(SLDestroy)
void SLDestroy(SL* ps) {
assert(ps);//检查ps是否为空
free(ps->a);//释放顺序表申请的内存
ps->size = 0;//有效数据个数置为0
ps->capacity = 0;//容积置为0
}
2.3顺序表的打印(SLPrint)
void SLPrint(SL* ps) {
assert(ps);
int i = 0;
for (i = 0; i < ps->size; i++) {
printf("%d ", ps->a[i]);
}
}
2.4顺序表检查是否需要扩容(SLCheck_Capacity)
void SLCheck_Capacity(SL* ps) {
assert(ps);//检查ps是否为空
if (ps->capacity == ps->size) {
SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * ps->capacity * 2);
//进行扩容操作,先用tmp在ps-》a的基础上进行扩容
//因为realloc的机制若扩容是被则会得到NULL,若直接用ps-》a进行扩容
//若扩容失败则会把原来p->a指向的内存空间弄丢
if (tmp == NULL) {//判断扩容是否成功
perror("SLCheck_Capacity");
return;
}
//若成功则让ps->a接收新的地址
ps->a = tmp;
ps->capacity *= 2;//最大容积扩大了一倍
}
}
2.5顺序表的尾插(SLPushBack)
void SLPushBack(SL* ps,SLDataType x) {
assert(ps);//检查ps是否为空
SLCheck_Capacity(ps);//判断是否需要扩容
ps->a[ps->size] = x;//因为数组元素下标最大为size-1,
//所以新元素就下标为size
ps->size++;//有效数据加一
}
2.55顺序表的尾删(SLPopBack)
void SLPopBack(SL* ps) {
assert(ps);//检查ps是否为空
assert(ps->size > 0);//若size小于等于0,
//则有效数据已经不存在了
ps->size--;//有效数据减少一个,数组总大小并没有变
}
2.6顺序表的头插(SLPushFront)
void SLPushFront(SL* ps, SLDataType x) {
assert(ps);//检查ps是否为空
SLCheck_Capacity(ps);//判断是否需要扩容
int end = ps->size - 1;//指向最后一个元素
while (end >= 0) {
ps->a[end + 1] = ps->a[end];//从最后一个元素开始依次向后移动一个单位
end--;
}
ps->a[0] = x;//空出第一个位置给其赋值
ps->size++;//有效数据加一
}
2.65顺序表的头删(SLPopFront)
void SLPopFront(SL* ps) {
assert(ps);//检查ps是否为空
assert(ps->size > 0);//若size小于等于0,
//则有效数据已经不存在了
int begin = 1;
while (begin <= ps->size - 1) {//让后一个元素去覆盖前一个元素
ps->a[begin - 1] = ps->a[begin];//比如让下标为1去覆盖下标为0的元素,
//这样就达到了删除头元素的效果
begin++;
}
ps->size--;//有效数据减一
}
2.7顺序表的插入(SLInsert)
void SLInsert(SL* ps, int pos, SLDataType x) {
//pos为要插入位置的数组下标
assert(ps);
assert(pos >= 0 && pos <= ps->size);
SLCheck_Capacity(ps);//判断是否需要扩容
int end = ps->size - 1;//从最后一个元素开始,
//依次向后移动一位
//size位置放size-1的元素
while (end >= pos) {//到pos+1向后移动一位后结束
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[pos] = x;//让x去覆盖原来pos上的元素
//因为原先pos的元素已经被pos+1复制了,所以可以覆盖
ps->size++;
}
2.75顺序表的指定位置删除(SLErase)
void SLErase(SL* ps, int pos) {
assert(ps);
assert(pos >= 0 && pos < ps->size);//pos数值要有意义
int begin = pos + 1;
while (begin <= ps->size - 1) {
ps->a[begin - 1] = ps->a[begin];//从pos开始
//让其后面一个元素去覆盖前面一个元素
//下标为size-2的元素被下标为size-1的元素覆盖
begin++;
}
ps->size--;//有效数据减一
}
2.8顺序表的查找(SLFind)
int SLFind(SL* ps, SLDataType x)
{
assert(ps);
for (int i = 0; i < ps->size; ++i)
{//遍历寻找是否与x相同的元素
if (ps->a[i] == x)
{
return i;//若有则返回数组下标
}
}
return -1;//没有返回-1
}