前言:
还记得前面的文章:《通讯录的实现》吗?
通讯录的完成就借助了顺序表这种数据结构!!!
那么今天我们就来介绍我们的顺序表
介绍顺序表前,我们来了解一下线性表的概念
线性表:
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结
构,常见的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
顺序表:
什么是顺序表:
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组
上完成数据的增删查改。
顺序表:可动态增长的数组,要求数据是连续存储的
顺序表的分类:
一、静态顺序表:
typedef int SLDataType;
typedef struct SeqList
{
SLDataType array[N]; //定长数组
size_t size; //有效数据个数
}SeqList;
由上述代码:我们可以很清楚的看出,这个顺序表使用定长数组进行存储数据。
我们也很容易发现这个静态的顺序表有一个十分大的缺陷:
数组的大小不确定,如果你的N给小了,那么就会不够用,如果你的N给大了,又会造成浪费
所以我们如果使用顺序表就应该使用动态的顺序表:
二、动态顺序表:
typedef int SLDataType; //类型重命名,后续要存储其它类型时方便更改
typedef struct SeqList
{
SLDataType* SLD; //指向动态开辟的数组
size_t size; //有效数据个数
size_t capacity; //容量大小
}SeqList;
动态顺序表的实现:
初始化顺序表
void SeqListInit(SeqList* psl)
{
assert(psl);
psl->SLD = NULL;
psl->size = 0;
psl->capacity = 0;
}
销毁顺序表
void SeqListDestory(SeqList* psl)
{
assert(psl != NULL);
free(psl->SLD);
psl->SLD = NULL;
psl->size = 0;
psl->capacity = 0;
}
检查顺序表容量是否满了,好进行增容
void CheckCapacity(SeqList* psl)
{
assert(psl != NULL);
if (psl->size == psl->capacity)
{
size_t newcapacity;
if (psl->capacity == 0)
newcapacity = psl->capacity = 4;
else
newcapacity = 2 * psl->capacity;
SLDataType* p = (SLDataType*)realloc(psl->SLD, newcapacity * sizeof(SLDataType));
if (p == NULL)
{
perror("realloc");
exit(-1);
}
psl->SLD = p;
psl->capacity = newcapacity;
}
}
顺序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x)
{
assert(psl != NULL);
CheckCapacity(psl);
psl->SLD[psl->size] = x;
psl->size++;
}
顺序表尾删
void SeqListPopBack(SeqList* psl)
{
assert(psl != NULL);
assert(psl->size > 0);
psl->size--;
}
顺序表头插
void SeqListPushFront(SeqList* psl, SLDataType x)
{
assert(psl);
CheckCapacity(psl);
int i = 0;
for (i = psl->size - 1; i >= 0; i--)
{
psl->SLD[i + 1] = psl->SLD[i];
}
psl->SLD[0] = x;
psl->size++;
}
顺序表头删
void SeqListPopFront(SeqList* psl)
{
assert(psl);
assert(psl->size > 0);
int i = 0;
for (i = 1; i < psl->size; i++)
{
psl->SLD[i - 1] = psl->SLD[i];
}
psl->size--;
}
打印顺序表
void SeqListPrint(const SeqList* psl)
{
assert(psl != NULL);
if (psl->size == 0)
{
printf("顺序表为空\n");
return;
}
int i = 0;
for (i = 0; i < psl->size; i++)
{
printf("%d ", psl->SLD[i]);
}
printf("\n");
}
在顺序表中查找指定值
int SeqListFind(const SeqList* psl, SLDataType x)
{
assert(psl);
int i = 0;
for (i = 0; i < psl->size; i++)
{
if (psl->SLD[i] == x)
{
return i;
}
}
return -1;
}
在顺序表指定下标位置插入数据
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x)
{
assert(psl);
assert(pos >= 0 && pos <= psl->size);
CheckCapacity(psl);
size_t i = 0;
for (i = psl->size; i > pos; i--)
{
psl->SLD[i] = psl->SLD[i - 1];
}
psl->SLD[pos] = x;
psl->size++;
}
在顺序表中删除指定下标位置的数据
void SeqListErase(SeqList* psl, size_t pos)
{
assert(psl);
assert(psl->size > 0);
assert(pos >= 0 && pos < psl->size);
size_t i = 0;
for (i = pos + 1; i < psl->size; i++)
{
psl->SLD[i - 1] = psl->SLD[i];
}
psl->size--;
}
查看顺序表中数据个数
size_t SeqListSize(const SeqList* psl)
{
assert(psl);
return psl->size;
}
修改指定下标位置的数据
void SeqListAt(SeqList* psl, size_t pos, SLDataType x)
{
assert(psl);
assert(psl->size > 0);
assert(pos >= 0 && pos < psl->size);
psl->SLD[pos] = x;
}