引言
线性表是最基本、最简单、也是最常用的一种数据结构。 线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。 线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。 线性表是一种在实际中广泛使用的数据结构,常见的线性表: 顺序表、链表、栈、队列、字符串。… 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。 今天给大家介绍一下线性表中最简单一种: 顺序表。 顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系,采用顺序存储结构的线性表通常称为顺序表。 顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。
顺序表
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。 顺序表一般可以分为: 1.静态顺序表: 使用定长数组存储元素 2.动态顺序表: 使用动态开辟的数组存储
两种顺序表的比较: 静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表的各个接口的基本操作。
接口实现
void SeqListInit(SeqList* psl, size_t capacity);
void CheckCapacity(SeqList* psl);
void SeqListPushBack(SeqList* psl, SLDataType x);
void SeqListPopBack(SeqList* psl);
void SeqListPushFront(SeqList* psl, SLDataType x);
void SeqListPopFront(SeqList* psl);
int SeqListFind(SeqList* psl, SLDataType x);
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x);
void SeqListErase(SeqList* psl, size_t pos);
void SeqListDestory(SeqList* psl);
void SeqListPrint(SeqList* psl);
以上是我们要实现的接口功能。 接下来,我们一个一个的来具体分析、具体实现: 顺序表的动态存储:
typedef int SQDataType;
typedef struct SeqList
{
SQDataType* a;
int size;
int capacity;
}SLT;
顺序表初始化接口:
void SeqListInit(SLT* psl)
{
assert(psl);
psl->a = NULL;
psl->size = psl->capacity = 0;
}
顺序表销毁接口:
void SeqListDestory(SLT* psl)
{
assert(psl);
if (psl->a)
{
free(psl->a);
psl->a = NULL;
}
psl->size = psl->capacity = 0;
}
顺序表打印接口:
void SeqListPrint(SLT* psl)
{
assert(psl);
for (int i = 0; i < psl->size; ++i)
{
printf("%d ", psl->a[i]);
}
printf("\n");
}
顺序表检查增容:
void SeqListCheckCapcity(SLT* psl)
{
assert(psl);
if (psl->size == psl->capacity)
{
size_t newcapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;
psl->a = realloc(psl->a, newcapacity * sizeof(SQDataType));
psl->capacity = newcapacity;
}
}
顺序表尾插:
void SeqListPushBack(SLT* psl, SQDataType x)
{
assert(psl);
SeqListCheckCapcity(psl);
psl->a[psl->size] = x;
psl->size++;
}
顺序表头插:
void SeqListPushFront(SLT* psl, SQDataType x)
{
assert(psl);
SeqListCheckCapcity(psl);
int end = psl->size - 1;
while (end >= 0)
{
psl->a[end + 1] = psl->a[end];
--end;
}
psl->a[0] = x;
psl->size++;
}
顺序表尾删:
void SeqListPopBack(SLT* psl)
{
assert(psl);
if (psl->size > 0)
{
psl->size--;
}
}
顺序表头删:
void SeqListPopFront(SLT* psl)
{
assert(psl);
int begin = 1;
while (begin < psl->size)
{
psl->a[begin - 1] = psl->a[begin];
begin++;
}
if (psl->size > 0)
{
psl->size--;
}
}
顺序表查找接口:
int SeqListFind(SLT* psl, SQDataType x)
{
assert(psl);
for (int i = 0; i < psl->size; i++)
{
if (psl->a[i] == x)
{
return i;
}
}
return -1;
}
顺序表插入数据接口(2种):
void SeqListInsert(SLT* psl, size_t pos, SQDataType x)
{
assert(psl);
assert(pos < psl->size);
SeqListCheckCapcity(psl);
size_t end = psl->size ;
while (end > pos)
{
psl->a[end] = psl->a[end-1];
end--;
}
psl->a[pos] = x;
psl->size++;
}
顺序表删除数据接口:
void SeqListErase(SLT* psl, size_t pos)
{
assert(psl);
assert(pos < psl->size);
size_t begin = pos + 1;
while (begin < psl->size)
{
psl->a[begin - 1] = psl->a[begin];
begin++;
}
psl->size--;
}
顺序表求数组中数据个数:
size_t SeqListSize(SLT* psl)
{
assert(psl);
return psl->size;
}
顺序表修改pos位置的数据接口:
void SeqListAt(SLT* psl, size_t pos, SQDataType x)
{
assert(psl);
assert(pos < psl->size);
psl->a[pos] = x;
}
以上就是顺序表的基本接口功能的实现,相信大家在看完之后,一定对顺序表方面的知识有所掌握和了解。
|