目录
写在开头:不积硅步,无以至千里
顺序表的结构
顺序表的数据存储
顺序表之所以被称为顺序表,就是因为顺序表所开辟的内存空间是连续的,因为要开辟一段连续的内存空间,所以我们很自然的想到使用内存函数来开辟这段内存。
我们先来回顾本次会使用到的两个内存函数:malloc和realloc
malloc:
声明:
void *malloc( size_t size );
参数:size是需要开辟的字节数
返回值:返回一个指针,指向开辟的内存空间;如果开辟失败,则返回一个空指针
realloc:
声明:
void *realloc( void *memblock, size_t size );
参数:
- memblock指向需要重新分配内存的空间
- size是需要重新分配给这块空间的字节数
返回值:返回一个指针,指向重新分配内存的空间
自定义顺序表的成员
我们已经知道,顺序表的数据要存储到一块连续的空间,而这块空间是我们动态开辟出来的,所以在我们的顺序表成员变量中,我们需要一个指针来接收这块空间的起始位置,同时,我们需要一个变量来记录目前占用的个数,需要另外一个变量记录顺序表一共开辟了多少数量。
typedef int SLDataType;
struct SeqList
{
SLDataType* a;
int size;
int capacity
};
*备注::这里我们将int重定义为SLDataType是为了方便以后修改其他数据
为了方便,我们将我们自定义的结构体重新定义为SL,并创建一个SL类型的变量s1
typedef int SLDataType;
typedef struct SeqList
{
SLDataType* a;
int size;
int capacity
}SL;
SL s1;
顺序表的初始化
完成上面的操作后,我们需要初始化一下我们的顺序表,我们通过一个简单的函数实现了初始化
#include <stdio.h>
void SLInit(SL* ps)
{
ps->a = NULL;//使用NULL记得引头文件哦
ps->size = 0;
ps->capacity;
}
顺序表的增删查改
检查容量
在进行增删查改操作之前,我们的s1中的a还没有指向任何空间,因为在后期很多操作中我们都会检查容量是否已满并考虑扩容,因此我们封装一个函数来检查当前容量,如果不够就扩容
void SLCheckcapacity(SL* ps)
{
assert(ps);
if (ps->size == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
SLDataType* tmp = (SLDataType*)realloc(ps, newcapacity *sizeof(SLDataType));
if (tmp == NULL)
{
perror("malloc fail::::");
exit(-1);
}
ps->a = tmp;
ps->capacity = newcapacity;
}
}
插入(增):
声明:
void SLInsert(SL* ps, int pos, SLDataType x);
变量:
- ps是SL*类型的指针,指向动态开辟的空间
- pos是要插入的位置,从0开始
- x是要插入的数值(SLDataType类型)
思路:
我们要在pos位置插入,就要把pos后面的全部向后挪走
首先我们记住最后一个元素的下标
void SLInsert(SL* ps, int pos, SLDataType x)
{
int end = ps->size - 1;
}
接下来将end指向的元素挪动到end-1的位置处,执行完后我们让end向左移动一下,直到end小于pos
void SLInsert(SL* ps, int pos, SLDataType x)
{
SLCheckcapacity(ps);//别忘了检查容量哦
int end = ps->size - 1;
while (end >= pos)
{
ps->a[end+1] = ps->a[end];
end--;
}
ps->a[pos] = x;
ps->size++;
}
删除(删):
声明:
void SLErase(SL* ps, int pos);
参数:
- ps是一个SL*类型的指针,指向开辟的空间
- pos是要删除的位置下标
思路:
将要删除的位置用后面的数据覆盖掉, 因此我们定义一个begin变量,让begin位置的数据放到begin的前一个位置,当begin<size的时候就停止
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(pos!=0);
int begin = pos + 1;
while (begin<ps->size)
{
ps->a[begin - 1] = ps->a[begin];
begin++;
}
ps->size--;
}
查找(查):
声明:
int SLFind(SL* ps,SLDataType x,int begin);
参数:
ps是指向开辟空间的指针
x是要查找的数据
begin是开始查找的位置
由于查找的本身逻辑很简单,在这里我只贴上代码,供大家参考
int SLFind(SL* ps, SLDataType x, int begin)
{
assert(ps);
for (int i = begin; i < ps->size; i++)
{
if (ps->a[i] == x)
{
return i;
}
}
return -1;
}
更改(改):
声明:
void SLRevise(SL* ps, SLDataType x, int pos);
参数:
- ps是指向开辟空间的指针
- pos是要修改的位置
- x是要修改的数值
void SLRevise(SL* ps, SLDataType x, int pos)
{
ps->a[pos] = x;
}
小结
如果你能坚持看到这里,相信你一定对顺序表有了一定的了解,请不要吝啬为笔者点赞,这是我更新的动力,锲而不舍,金石可镂,没有付出不会得到回报,最后,为努力学习知识的你点赞!