顺序表介绍
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存 储。在数组上完成数据的增删查改。
顺序表一般可以分为:
1. 静态顺序表:使用定长数组存储元素。 2. 动态顺序表:使用动态开辟的数组存储。
首先,我们要创建一个顺序表类型,该顺序表类型包括了顺序表的起始位置、记录顺序表内已有元素个数的计数器(size),以及记录当前顺序表的容量的变量(capacity)。
初始化顺序表 Init
//初始化
void SLInit(SL* ps)
{
assert(ps);
ps->arr = (SLDataType*)malloc(sizeof(SLDataType) * 4);
if (ps->arr == NULL)
{
perror("malloc failed");
exit(-1);
}
ps->size = 0;
ps->capacity = 4;
}
销毁顺序表 Destroy
//销毁
void SLDestroy(SL* ps)
{
assert(ps);
free(ps->arr);
ps->arr = NULL;
ps->capacity = 0;
ps->size = 0;
}
//注:因为顺序表所用的内存空间是动态开辟在堆区的
所以我们在使用完后需要及时对其进行释放,避免造成内存泄漏。
打印顺序表 Print
//打印
void SLPrint(SL* ps)
{
assert(ps);
//依次循环打印size个元素
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->arr[i]);
}
printf("\n");
}
检查顺序表容量 CheckCapacity
//检查顺序表容量是否已满,若已满,则增容
void SLCheckCapacity(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 failed");
exit(-1);
}
ps->arr = tmp;
ps->capacity *= 2;
}
}
//注意:若传入realloc的指针为空指针(NULL),则realloc函数的作用相当于malloc函数。
尾插尾删 头插头删
尾插 PushBack:直接在表尾插入数据即可。
尾删PopBack:直接将顺序表的元素个数减一即可。
void SLPushBack(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
ps->arr[ps->size] = x;
ps->size++;
}
void SLPopBack(SL* ps)
{
assert(ps);
SLCheckCapacity(ps);
assert(ps->size);
ps->size--;
}
头插PushFront:要想在顺序表的表头插入数据,那么就需要先将顺序表原有的数据从后往前依次向后挪动一位,最后再将数据插入表头。
头删PopFront:要删除表头的数据,我们可以从下标为1的位置开始,依次将数据向前覆盖即可。
void SLPushFront(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
int end = ps->size - 1;
while (end >= 0)
{
ps->arr[end + 1] = ps->arr[end];
end--;
}
ps->arr[0] = x;
ps->size++;
}
void SLPopFront(SL* ps)
{
assert(ps);
assert(ps->size > 0);
int begin = 1;
while (begin < ps->size)
{
ps->arr[begin - 1] = ps->arr[begin];
begin++;
}
}
指定位置插入 Insert
要做到在指定下标位置插入数据,首先我们需要得到一个下标位置,然后从该下标位置开始(包括该位置),其后的数据从后往前依次向后挪动一位,最后将数据插入到该下标位置。
// 在pos位置插入x
void SLInsert(SL* ps, int pos, SLDataType x)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
SLCheckCapacity(ps);
int end = ps->size - 1;
while (end >= pos)
{
ps->arr[end + 1] = ps->arr[end];
--end;
}
ps->arr[pos] = x;
ps->size++;
}
指定位置删除 Erase
要删除指定下标位置的数据,我们只需要从下标位置开始,其后的数据从前向后依次覆盖即可。
// 删除pos位置的值
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
int begin = pos + 1;
while (begin < ps->size)
{
ps->arr[begin - 1] = ps->arr[begin];
++begin;
}
ps->size--;
}
查找指定数据 Find
直接遍历一次顺序表即可,若找到了目标数据,则停止遍历,并返回该数据的下标,否则返回-1。
//顺序表查找x
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;
}
修改指定位置 Modify
修改数据,就直接对该位置的数据进行再次赋值即可。
//修改pos位置的值为x
void SLModify(SL* ps, int pos, SLDataType x)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
ps->arr[pos] = x;
}