![](https://img-blog.csdnimg.cn/95e7d5c06557402a8a64f54beca2741d.png)
struct SeqList{
int a[100];
int size; //有效数据个数
}
空间不够造成数据无法存储,在实际场景中,若数据无法有效保存,就会造成数据丢失
静态顺序表的特点:
空间给小了不够用,给多了造成空间浪费。
//动态顺序表--按需申请
struct SeqList{
int *a;
int size;//有效数据的个数
int capacity;//空间大小
}
二:顺序表的相关操作
结构体的重命名,简化其名,用之顺手尔
//动态顺序表
typedef int SLDataType;
struct SeqList
{
SLDataType* a;
int size;//顺序表中有效的数据个数
int capacity;//顺序表当前的空间大小
};
typedef struct SeqList SL;
在这个代码中 我们把类型 为:struct SeqList 重命名为SL
typedef struct SeqList SL;
当我们所写的结构体给他人使用时,我们并不知道他要使用那种类型所以就不仅仅是我们缩写的int类型,我们可以写成 typedef int SLDataType;
而我们在定义数据域的时候需要写成
SLDataType*a;
# define INIT_CAPACITY 4typedef int SLDataType;// 动态顺序表 -- 按需申请typedef struct SeqList{SLDataType* a;//可以实现其他类型int size; // 数据表的有效个数int capacity; //顺序表的大小}SL;//函数声明void SLInit (SL* ps);//初始化void SLDestroy (SL* ps);//销毁void SLPrint (SL* ps);//打印// 扩容void SLCheckCapacity (SL* ps);// 头部插⼊删除 / 尾部插⼊删除void SLPushBack (SL* ps, SLDataType x);//尾插void SLPopBack (SL* ps);//尾删void SLPushFront (SL* ps, SLDataType x);//头插void SLPopFront (SL* ps);//头删// 指定位置之前插⼊ / 删除数据void SLInsert (SL* ps, int pos, SLDataType x);//指定位置插入void SLErase (SL* ps, int pos);//指定位置删除int SLFind (SL* ps, SLDataType x);
顺序表里面涉及函数的具体实现
1.顺序表的初始化
void SLInit(SL *ps) {
ps ->a = NULL;//结构体成员访问操作符 一个是. 一个是->
//结构体变量.成员变量名 结构体指针->成员变量名
ps ->size = ps->capacity = 0;
}
2.顺序表的销毁
void SLDestroy(SL* ps)//销毁
{
if (ps->a)//判断所指向的空间是否为空
{
free(ps->a);//free只能用来释放掉动态内存开辟的空间如malloc calloc realloc所开辟的空间
ps->a = NULL;
}
ps->size = ps->capacity = 0;
}
3.顺序表的打印
遍历数组,然后打印出来
void SLPrint(SL* ps)
{
for (size_t i = 0; i < ps->size; i++)//这里的size_t 写成int也是可以的
{
printf("%d", ps->a[i]);
}
printf("\n");
}
4,尾插
尾插就是在数组的末尾插入一个数据,
如果我们想要在3后面插入一个数据,就要在下标为4的位置插入,也就是size-1的位置
当我们空间足够的时候,我们可以直接插入数据,而我们空间不够呢,我们之前在动态内存管理中介绍过
malloc():向内存申请一块连续的空间,且不初始化
calloc():向内存申请一块连续的空间,且初始化为0
realloc():向内存申请一块连续的空间不初始化,如果申请空间时,后面有的空间已经被占用,就会重新找一块连续的空间,且会把之前的数据拷贝下来。
而我们这里用到的是realloc()来开辟空间,因为他零活多变(就像你老板让三个人买西红柿,malloc和calloc只会 买西红柿,而realloc还会把卖西红柿的农人带到公司来商量供应事宜);
在插入数据之前,我们要判断空间是否足够我们插入数据,如果不够就需要扩容
void SLCheckCapacity(SL* ps) {
if (ps->size == ps->capacity)
{//空间不足的时候额外插入一个数据
//扩容
int newCapcity = ps->capacity == 0 ? 4 : 2 * ps -> capacity;
SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapcity * sizeof(SLDataType));
if (tmp == NULL)
{
perror("realloc fail!\n");
return 1;
}
ps->a = tmp;
ps->capacity = newCapcity;
}
尾插
//尾插
void SLPushBack(SL* ps, SLDataType x)
{
//assert(ps!=NULL);
//暴力的方法
assert(ps);//确保指针的有效性
//先确认是否有空间可以插入 不够就扩容
//够了直接尾插
SLCheckCapacity(ps);//因为SLCheckCapacity()函数中我们已经做好了判断,
//所以不需要我们再判断
//直接插入数据
ps->a[ps->size++] = x;
}
5头插
头插,就是再再下标为0的位置插入数据,之前的数据全部后移,那么是先后移,还是先插入,如果我们先插入就会把第一个数据0覆盖,所以我们要先后移数据,俗话说的好打扫干净屋子再请客
//头插
void SLPushFront(SL* ps, SLDataType x)
{
assert(ps);//惯例断言
//惯例先判断空间是否足够,如果不够就扩容
SLCheckCapacity(ps);
//空间足够,全体后移
for (size_t i = ps->size; i > 0; i--)
{
ps->a[i] = ps->a[i - 1];
}
ps->a[0] = x;//把要插入的数据请进来
ps->size++;//我们多了一个人,所以我们空间就要加1.
}
6,尾删
判空
bool SLIsEmpty(SL* ps)//头文件 <stdbool.h>
{
assert(ps);
//这样子是不对的,这里只能判断空间是否足够
//return ps->size == ps->capacity;
return ps->size == 0;
}
void SLPopBack(SL* ps)
{//判断顺序表是否为空
assert(ps);
assert(!SLIsEmpTY(ps));
//assert(IsEmpty(ps))这样写是不对的 assert()断言是用来判断里面的表达式是真还是假,
//只有为假的话,这个断言才会生效
//ps->a[ps->size -1]=0;
ps->size--;//没有必要进行赋值,直接size--
}
7头删
void SLPopFront(SL* ps)
{
assert(ps);//我们要判断一下顺序表是否为空
aeesrt(!SLIsEmpty(ps));
//让后面的数据往前挪动一位
for (size_t i = 0; i < ps->size - 1; i++)
{
ps->a[i] = ps->a[i + 1];//我们只需要用后面的数据覆盖前面的数据,
//就可以实现头删
}
ps->size--;
}
8.指定位置插入数据
//指定位置插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{
assert(ps);
//不要忘了对pos加以限制
assert(pos >= 0 && pos <= ps->size);
//管理 扩容
SLCheckCapacity(ps);
//我所指定的位置以后的都有向后移
for (int i = ps->size - 1; i > pos - 1; i--)
{
//最后一次进来的i是pos
ps->a[i + 1] = ps->a[i];//ps->a[pos+i]=ps->a[pos]
}
ps->a[pos] = x;
ps->size++;
}
9.删除指定位置数据
首先我们肯定要判断顺序表是否为空,指定的位置是否有效,但是这次我们不需要判断空间是否足够大(这次不吃你家大米饭);
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(!SLIsEmpty);
//限定pos范围
assert(pos >= 0 && pos < ps->size);
for (int i = pos; i < ps->size - 1; i++)
{//删除指定位置的数据,我们只需要用指定位置后面的数据往前移,覆盖掉即可
//最后一次进来的i的数据ps->size-2
ps->a[i] = ps->a[i + 1];//ps->a[ps->size-2]=ps->a[ps->size-1]
}
ps->size--;
}
好的,顺序表专题就此结束,我们顺序表 通讯录见