顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存
储。在数组上完成数据的增删查改。
静态顺序表——使用定长数组储存数据
静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空
间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间
大小,
动态顺序表
动态顺序表的实现
多应用文件的形式写代码:text.c ——测试
seqlist,c ——函数实现
seqlist.h ——函数的声明
首先在头文件中创建一个动态顺序表的内存储存结构体
#include<stdio.h>
#include<stdlib.h>
typedef int SLDataType;
typedef struct SeqList
{
SLDataType* a;//指向动态开辟的数组
int size;//记录有效数组个数
int capicity;//记录空间大小
}SL;//重名名为SL
然后在text.c中的main函数中定义一个结构体变量s,
int main()
{
SL s;
SLInit(&s);//传址才能改变形参
return 0;
}
然后再seqlist.c中实现顺序表的初始化
void SLInit(SL* p)
{
p->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);//开辟4个空间
if (p->a == NULL)
{
perror("malloc faild");
exit(-1);
}
p->size = 0;
p->capicity = 4;
}
在顺序表的末尾增加数据
主函数调用传参就可以增加了
int main()
{
SL s;
SLInit(&s);//传址才能改变形参
SLPushBack(&s, 1);
SLPushBack(&s, 2);
SLPushBack(&s, 1);
SLPushBack(&s, 3);
SLPushBack(&s, 4);
SLPushBack(&s, 5);
PRint(&s);
SLDestroy(&s);
return 0;
}
void SLPushBack(SL* p, SLDataType x)
{
if (p->size == p->capicity)//如果相等就要增容
{
SLDataType* ps = (SLDataType*)realloc(p->a, p->capicity * 2 * (sizeof(SLDataType)));
if (ps == NULL)
{
perror("realloc faild");
exit(-1);
}
p->a = ps;
p->capicity *= 2;
}
p->a[p->size] = x;
p->size++;
}
void PRint(SL* p)
{
for (int i = 0; i < p->size; i++)
{
printf("%d ", p->a[i]);
}
printf("\n");
}
在顺序表的末尾删除数据
——直接size–把末尾的有效数据删了,空间capicity不变,但是要注意不能越界,所以删除函数中还要写代码来检测是否删除越界了(szieof<0)
void SLPoBack(SL* p)
{
//当size小于0后,就不删了
//温柔的方法
/*if (p->size == 0)
return;*/
//强制的方法——越界了就直接给报错
assert(p->size > 0);
p->size--;
}
在顺序表的头部插入数据
——整体数据向后挪动,给要插入的数据腾出首位置
因为这种方法也要考虑需不需要曾容的问题,所以直接把增容的代码也打包成一个函数封装使用
void SLPushFront(SL* p, SLDataType x)
{
SLCheckCapacity(p);//判断增容函数
//挪动数据
int end = p->size - 1;
while (end >= 0)
{
p->a[end+1] = p->a[end];
end--;
}//这样就实现了原有数据的整体向后挪动
p->a[0] = x;//首位置增加数据
p->size++;//有效数据+1
}
头部删除数据——直接用后面的数据覆盖
void SLPopFront(SL* p)
{
//当没有数据的时候如果还删的话就会出现越界报错
assert(p->size>0);
//挪动数据
int exit =1;
while (exit<p->size)
p->a[exit-1] = p->a[exit];
++exit;
}//这样就实现了原有数据的整体向后挪动
p->size--;//有效数据+1
}
在pos位置插入x
代码:
void SLInsert(SL* p, int pos, SLDataType x)
{
assert(pos >= 0 && pos <= p->size);
SLCheckCapacity(p);//判断增容函数,因为如果pos=size那么就是在末尾增加数据,就要判断是否要增容
int end = p->size - 1;
while (end >= pos)
{
p->a[end + 1] = p->a[end];
end--;
}
p->a[pos] = x;
p->size++;
}
有了这个方法,那么我们在之前的头增尾增的代码就可以改成直接调用这个函数就行
删除pos位置的值
代码:
void SLErase(SL* p, int pos)
{
assert(pos >= 0 && pos < p->size);
int begin = pos + 1;
while (begin < p->size)
{
p->a[begin - 1] = p->a[begin];
begin++;
}
p->size--;
}