先展示代码声明部分
头文件SeqList.h:
#define _CRT_SECURE_NO_WARNINGS
#pragma once//防止多重包含头文件导致重定义错误或者链接编译失败
#include <stdio.h>
#include <stdlib.h>
typedef int SLDatatype;//动态定义数据存储类型,方便修改
typedef struct SeqList
{
int size;//表示存储了多少个数据元素
int capacity;//表示表的存储空间大小
SLDatatype* a;//表示表的头指针
}SL;//简写成SL
void SLInit(SL* sl);//初始化函数
void SLDestroy(SL* sl);//回收函数
void SLPushBack(SL* sl,SLDatatype x);//头插函数
void SLPushFront(SL* sl, SLDatatype x);//尾插函数
void SLPopBack(SL* sl);//头删函数
void SLPopFront(SL* sl);//尾删函数
void SLPrint(SL* sl);//打印函数
void SLCheckCapacity(SL* sl);//检查存储空间大小函数
void SLInsert(SL* sl, int pos, SLDatatype x);//插入指定位置元素函数
void SLErase(SL* sl, int pos);//删除指定位置函数
int SLFind(SL* sl, SLDatatype x);//查找函数
void SLModify(SL* sl, int pos, SLDatatype x);//修改函数
函数实现部分SeqList.c:
#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"
#include <assert.h>//导入断言头文件
void SLInit(SL* sl)
{
assert(sl);
sl->a = (SLDatatype*)malloc(sizeof(SLDatatype)*4);
if (sl->a == NULL)//检查malloc函数是否开辟空间成功,该函数如果开辟失败返回空指针
{
perror("malloc fail");
exit(1);//我的建议使用exit而不是return,因为return会引起void返回值警告
}
sl->capacity = 0;//开始时全部初始化为0
sl->size = 0;
}
void SLDestroy(SL* sl)
{
free(sl->a);//释放掉头指针
sl->a = NULL;//将相关元素全部清零
sl->capacity = 0;
sl->size = 0;
}
void SLPushBack(SL* sl, SLDatatype x)
{
assert(sl);
SLCheckCapacity(sl);//在所有插入函数插入逻辑执行之前先进行存量检查
sl->a[sl->size++] = x;
}
void SLPushFront(SL* sl, SLDatatype x)
{
assert(sl);
SLCheckCapacity(sl);
int end = sl->size-1;//这里从后往前依次挪动
while (end >= 0)
{
sl->a[end + 1] = sl->a[end];
end--;
}
sl->a[0] = x;
sl->size++;
}
void SLCheckCapacity(SL* sl)
{
if (sl->size == sl->capacity)
{
//这里使用三目操作符,表示如果容量为0,则设为4,如果不为零则扩容两倍
int newcapacity = sl->capacity == 0 ? 4 * sizeof(SLDatatype) : sl->capacity * 2;
SLDatatype* tmp = (SLDatatype*)realloc(sl->a, newcapacity);
//这里在原来的基础上扩容建议使用realloc函数,该函数会查看原地址后面是否有足够空间,
如果有则原地扩容,如果没有则进行复制拷贝到新的大内存块中返回新地址
if (tmp == NULL)
{
perror("realloc fail");
exit(2);
}
sl->a = tmp;
sl->capacity = newcapacity;
}
}
void SLPopBack(SL* sl)
{
assert(sl && sl->size > 0);//防止空的情况
sl->size--;//这里只需要讲size减掉让代码访问不到即可
}
void SLPopFront(SL* sl)
{
assert(sl && sl->size > 0);//防止空的情况
int start = 0;
while (start < sl->size - 1)
{
sl->a[start] = sl->a[start + 1];
start++;
}
sl->size--;
}
void SLPrint(SL* sl)
{
for (int i = 0; i < sl->size; i++)
{
printf("%d\n", sl->a[i]);
}
}
void SLInsert(SL* sl, int pos, SLDatatype x)
{
assert(sl && pos <= sl->size); // 确保顺序表非空,并且插入位置合法
SLCheckCapacity(sl); // 检查是否需要扩容
int end = sl->size - 1;
// 从最后一个元素开始向后移动,直到到达插入位置
while (end >= pos)
{
sl->a[end + 1] = sl->a[end];
end--;
}
sl->a[pos] = x; // 在指定位置插入新元素
sl->size++; // 更新顺序表的大小
}
void SLErase(SL* sl, int pos)
{
assert(sl && sl->size > 0 && pos < sl->size); // 确保顺序表非空,且位置合法
for (int i = pos; i < sl->size - 1; i++)
{
sl->a[i] = sl->a[i + 1]; // 将删除位置之后的元素向前移动
}
sl->size--; // 更新顺序表的大小
}
// 查找函数:查找指定值的元素,并返回其索引
int SLFind(SL* sl, SLDatatype x)
{
assert(sl); // 确保顺序表不为空
for (int i = 0; i < sl->size; i++)
{
if (sl->a[i] == x)
{
return i; // 找到匹配的值,返回其索引
}
}
return -1; // 如果没找到,返回 -1
}
// 修改函数:将指定位置的元素修改为新的值
void SLModify(SL* sl, int pos, SLDatatype x)
{
assert(sl && pos < sl->size); // 确保顺序表不为空,且位置合法
sl->a[pos] = x; // 修改指定位置的元素
}
调用测试部分test.c
#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"
int main()
{
SL s;
SLInit(&s);
SLPushBack(&s, 1);
SLPushBack(&s, 2);
SLPushBack(&s, 3);
SLPushFront(&s, 0);
SLPopBack(&s);
SLPopFront(&s);
SLInsert(&s, 1, 4);
SLErase(&s, 1);
SLModify(&s, 1, 3);
SLPrint(&s);
SLDestroy(&s);
return 0;
}
测试结果如图: