目录
概念及结构
接口实现
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表一般可以分为:
1. 静态顺序表:使用定长数组存储元素。
2. 动态顺序表:使用动态开辟的数组存储。
静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。
typedef int SLDataType;
//s顺序表的动态存储
typedef struct SeqList
{
SLDataType* p;//指向动态开辟的数组
int size; //有效数据个数
int capacity; //容量空间大小
}SL;
//顺序表销毁与初始化
void SLDestroy(SL* ps);
void SLInit(SL* ps);
//顺序表尾插
void SLPushBack(SL* ps, int i);
//顺序表头插
void SLPushFront(SL* ps, int i);
//顺序表尾删
void SLPopBack(SL* ps);
//顺序表头删
void SLPopFront(SL* ps);
//顺序表打印
void SLPrint(SL* ps);
//顺序表任意插入
void SLInsert(SL* ps, int pos, SLDataType n);
//顺序表任意删除
void SLErase(SL* ps, int pos);
//顺序表查找元素
int SLFind(SL* ps, SLDataType i);
//顺序表修改元素
int SLModify(SL* ps, int pos, SLDataType i);
那么接下来,我们看这些接口是如何实现的。
1.顺序表初始化SLInit:
void SLInit(SL* ps)
{
assert(ps);
ps->p = (SLDataType*)malloc(4 * sizeof(SLDataType));//顺序表初始化时,开辟四个整形大小
if (ps->p == NULL)
{
perror("malloc");
return;
}
ps->capacity = 4;
ps->size = 0;
}
2.顺序表销毁SLDestory:
void SLDestroy(SL* ps)
{
assert(ps);
free(ps->p);
ps->p = NULL;
ps->capacity = 0;
ps->size = 0;
}
3.检查顺序表容量是否够用:
void CheckCapacity(SL* ps)
{
assert(ps);
if (ps->size == ps->capacity)
{
//容量不够,则扩充为原来的两倍
SLDataType* tmp = realloc(ps->p, 2 * (ps->capacity) * sizeof(SLDataType));
if (tmp != NULL)
{
ps->p = tmp;
ps->capacity *= 2;
}
else
{
perror("malloc");
return;
}
}
}
4.顺序表尾插:
void SLPushBack(SL* ps, int i)
{
assert(ps);
CheckCapacity(ps);//每次尾插前检查容量
ps->p[ps->size] = i;
ps->size++;
}
5.顺序表头插:
void SLPushFront(SL* ps, int i)
{
assert(ps);
CheckCapacity(ps);
//memmove((ps->p)+1,ps->p,sizeof(SLDataType)*(ps->size));//这种挪动元素方式可以
int n = 0;
for (n = ps->size-1; n >= 0; n--)//这种挪动元素方式也可以
{
ps->p[n+1] = ps->p[n];
}
ps->p[0] = i;
ps->size++;
}
6.顺序表尾删:
void SLPopBack(SL* ps)
{
assert(ps);
//暴力检查
assert(ps->size > 0);
//温柔检查
/*if (ps->size == 0)
return;*/
ps->size--;
}
7.顺序表头删:
void SLPopFront(SL* ps)
{
assert(ps);
assert(ps->size > 0);
int i = 0;
for (i = 0; i < ps->size-1; i++)
{
ps->p[i] = ps->p[i + 1];
}
ps->size--;
}
8.顺序表打印:
void SLPrint(SL* ps)
{
assert(ps);
int i = 0;
for (i = 0; i < ps->size; i++)
{
printf("%d ",ps->p[i]);
}
}
9.顺序表任意插入
void SLInsert(SL* ps, int pos, SLDataType n)
{
assert(ps);
//暴力检查插入位置是否合理
assert(pos >= 0 && pos <= ps->size);
CheckCapacity(ps);
int end = ps->size - 1;
while (end >= pos)
{
ps->p[end + 1] = ps->p[end];
end--;
}
ps->p[pos] = n;
ps->size++;
}
10.顺序表任意删除
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(ps->size > 0);
//暴力检查插入位置是否合理
assert(pos >= 0 && pos <= ps->size - 1);
int start = pos;
while (start < ps->size-1)
{
ps->p[start] = ps->p[start + 1];
start++;
}
ps->size--;
}
11.顺序表查找元素
int SLFind(SL* ps, SLDataType i)
{
assert(ps);
int n = 0;
for (n = 0; n < ps->size; n++)
{
if (ps->p[n] == i)
{
return n;
}
}
return -1;//没找到返回-1
}
12.顺序表修改元素
int SLModify(SL* ps, int pos, SLDataType i)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
ps->p[pos] = i;
}