首先的话是要确定一件事就是顺序表是线性表的一种
是逻辑结构和物理结构都是线性的
逻辑结构就是大脑之中理解时而进行的架构
物理结构就是存储在内存空间之中的结构
分为静态和动态的顺序表
首先是扩容,增容,malloc是申请,calloc是加初始化,realooc是增容
接下来就是属于代码
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define N 1000
typedef int SLDataType;
////静态顺序表
//typedef struct SeqList {
// SLDataType arr[N];
// int size; //有效数据个数
//}SL;
//typedef struct SeqList SL
//动态顺序表
typedef struct SeqList {
SLDataType* arr;
int size; //有效数据个数
int capacity; //容量大小
}SL;
void SLPrint(SL* ps);
//初始化
void SLInit(SL* ps);
//销毁
void SLDesTroy(SL* ps);
//尾插
void SLPushBack(SL* ps, SLDataType x);
//头插
void SLPushFront(SL* ps, SLDataType x);
//尾删
void SLPopBack(SL* ps);
//头删
void SLPopFront(SL* ps);
int SLFind(SL* ps, SLDataType x);
//指定位置之前插⼊数据
void SLInsert(SL* ps, int pos, SLDataType x);
//删除指定位置的数据
void SLErase(SL* ps, int pos);
首先先是头文件,头文件就是目录,方便之后进行更改
顺序表要知道大小(有效数据个数)和数据存储,
同时为了方便之后进行更改,那么就是将数据类型进行一个更改
同时为了方便之后去写,那么就是将seqlist重命名为SL
正常情况肯定是动态顺序表好用,静态不知道是否够用且空间浪费不可控
那么就是为了方便跟新,就是需要加一个代码方便更新
void SLcheckCapacity(SL* ps)
{
//空间不够,申请空间
if (ps->size == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;//三目表达式
//空间不够-2倍增容
SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));
if (tmp == NULL)
{
perror("realloc fail!");
exit(1);
}
ps->arr = tmp;
ps->capacity = newCapacity;
}
}
这个是之后都需要判定的
realloc是属于要增加一个数据
正常情况肯定是需要增加两倍
是为了方便空间不浪费太多,也是为了没有频繁的调用而浪费时间
三目操作符就是表达是否是零
接下蓝就是realloc,前面是类型,后面是首地址还有要增加的大小
之后将数据进行一个改变
一个是首地址(realloc是如果原地址不够就会换一个足够的)
一个是容量,同时判断以下有没有增容失败
perror退出加爆出括号里面的内容
首先的话是需要初始化
void SLInit(SL* ps)
{
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
这个就是将空间的内容为空,同时将长度设置为零
同时还有容量,这个就是设置为零
这里传输的话肯定是需要改变的,因为要更改的话那么就是需要为实参
(.是值,->是地址,),这里完全不需要拷贝的,直接就是可以的
接下来就是属于销毁了
void SLDesTroy(SL* ps)
{
if(ps->arr)
free(ps->arr);
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
接下来是要插入数据
首先是尾插,插入最后一个合法的数据
void SLPushBack(SL* ps, SLDataType x)
{
////温柔的处理方式
//if (ps == NULL)
//{
// return;
//}
//粗暴---断言
//为真-通过,为假-报错
assert(ps != NULL);
SLcheckCapacity(ps);
ps->arr[ps->size++] = x;
}
相当的简单
size每次++,基本上都是属于可以让size都处于有效的数组的后面的一个位置
接下就是属于头插
void SLPushFront(SL* ps, SLDataType x)
{
assert(ps); //等价于assert(ps != NULL)
SLcheckCapacity(ps);
//直接头插
//数据整体向后挪动一位
for (int i = ps->size; i > 0 ;i--)
{
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[0] = x;
++ps->size;
}
首先是确定代码不是空的,同时判断大小够不够
接下蓝需要整体往后挪一位
之后将第一个位设置为相应的数据
接下来就是属于增加size
之后就是打印方便调试显示
void SLPrint(SL* ps)
{
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->arr[i]);
}
printf("\n");
}
之后是删除
//尾删
void SLPopBack(SL* ps)
{
assert(ps && ps->size);
--ps->size;
}
//头删
void SLPopFront(SL* ps)
{
assert(ps && ps->size);
for (int i = 0; i < ps->size-1; i++)
{
ps->arr[i] = ps->arr[i + 1];
}
--ps->size;
}
之后是查找
//查找x,查找到了就返回对应数据下标
int SLFind(SL* ps, SLDataType x)
{
for (int i = 0; i < ps->size; i++)
{
if (ps->arr[i] == x)
{
//找到了,返回下标
return i;
}
}
//没找到,返回无效下标
return -1;
}
指定位置插入删除
//指定位置之前插⼊数据
void SLInsert(SL* ps, int pos, SLDataType x)
{
assert(ps);
//前=:头插
//后=:尾插
assert(pos >= 0 && pos <= ps->size);
SLcheckCapacity(ps);
for (int i = ps->size; i > pos ;i--)
{
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[pos] = x;
++ps->size;
}
//删除指定位置的数据
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
for (int i = pos; i < ps->size - 1; i++)
{
ps->arr[i] = ps->arr[i + 1];
}
--ps->size;
}