线性表指的是具有部分相同特性的⼀类数据结构的集合,它是由零个或多个数据元素组成的有限序列。
线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。
常见的线性表:顺序表、链表、栈、队列、字符串......
顺序表是使用一组连续的存储单元依次存储线性表的数据元素。链表则是通过节点将数据元素链接起来,节点包含数据域和指针域,指针域用于指向下一个节点。
顺序表的底层结构是数组,对数组的封装,实现了常用的增删改查等接口。它使用一组地址连续的存储单元依次存储线性表中的元素。顺序表分为静态顺序表和动态顺序表。
静态顺序表
typedef int Seqdatatype;
#define N 10
typedef struct SeqList
{
Seqdatatype a[N]; //定长数组
int size; //有效数据个数
}sl;
静态顺序表是指采用静态数组来实现的顺序表。它在使用前需要预先分配固定大小的存储空间,一旦分配完成,其容量就不能再改变。
静态顺序表的优点是实现简单,操作直观。
缺点也较为明显:空间大小固定,可能会出现存储空间不足或者浪费的情况。
动态顺序表是在顺序表的基础上,能够根据实际需求动态地调整存储空间大小。它的实现通常基于底层的数组,当现有存储空间不足时,会重新分配一块更大的连续存储空间,并将原数据复制到新的空间中。
动态顺序表的优点在于:
1. 能够更灵活地适应数据规模的变化,避免了因存储空间固定而导致的数据存储受限问题。
2. 相对于链表,它在随机访问上具有更高的效率。
不足之处在于:
1. 动态扩展存储空间时,涉及数据的复制操作,会带来一定的时间开销。
2. 频繁的扩展操作可能导致内存碎片的产生。
在实际应用中,如果需要高效的随机访问,同时数据规模不确定或可能发生较大变化,动态顺序表是一个较好的选择。
typedef struct SeqList
{
Seqdatatype* arr;
int size; //有效数据个数
int capacity; //空间大小
}SL;
下面是动态顺序表的实现:
我们将在三个文件中实现动态顺序表,头文件SeqList.h中实现函数的声明,源文件SeqList中实现函数的定义
text.c :
#include "SeqList.h"
test1()
{
SL sl;
SLInit(&sl);
//尾插
SLPushBack(&sl, 1);
SLPushBack(&sl, 2);
SLPushBack(&sl, 3);
SLPushBack(&sl, 4);
SLPrint(sl);
//头插
SLPushFront(&sl, 9);
SLPushFront(&sl, 8);
SLPushFront(&sl, 7);
SLPrint(sl);
//尾删
SLPopBack(&sl);
SLPopBack(&sl);
SLPrint(sl);
//头删
SLPopFront(&sl);
SLPopFront(&sl);
SLPrint(sl);
//指定位置
SLInsert(&sl, 66, 2);
SLPrint(sl);
//指定删除
SLErase(&sl, 1);
SLPrint(sl);
//查找数据
int find = SLFind(&sl, 66);
if (find < 0)
{
printf("没找到\n");
}
else
{
printf("找到了\n", find);
}
SLDestory(&sl);
}
int main()
{
test1();
return 0;
}
SeqList.h:
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include
#include
#include
typedef int SLDataType;
typedef struct SeqList
{
SLDataType* data;
int size;
int Capacity;
}SL;
//初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestory(SL* ps);
//打印
void SLPrint(SL s);
//判断空间充足
void SLCheckCapacity(SL* ps);
//尾插
void SLPushBack(SL* ps , SLDataType x);
//头插
void SLPushFront(SL* ps, SLDataType x);
//尾删
void SLPopBack(SL* ps);
//头删
void SLPopFront(SL* ps);
//指定位置之前插入数据
void SLInsert(SL* ps, SLDataType x,int pos);
//指定位置删除数据
void SLErase(SL* ps, int pos);
//查找数据
int SLFind(SL* ps, SLDataType x);
SeqList.c:
#include "SeqList.h"
//初始化
void SLInit(SL* ps)
{
ps->data = NULL;
ps->size = ps->Capacity = 0;
}
//顺序表的销毁
void SLDestory(SL* ps)
{
if(ps)
{
free(ps->data);
}
ps->data = NULL;
ps->size = ps->Capacity = 0;
}
//打印
void SLPrint(SL s)
{
for(int i = 0;i size == ps->Capacity)
{
int NewCapacity = ps->Capacity == 0 ? 4 : 2 * ps->Capacity;
SLDataType* tmp = (S