目录
线性表
**线性表是n个具有相同特性的数据元素的有限序列。**线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表,链表,栈,队列,字符串.......
线性表在逻辑上是线性结构,也就是说是连续的一条直线。 但是在物理结构上并不一定是连续的,线性表在物理上储存时,通常以数组和链表的形式存储。
顺序表
概念与结构
顺序表是用一段物理地址连续的储存单元依次存储数据元素的线性结构,一般情况下采用数组存储。
顺序表
顺序表和数组的区别?
顺序表的底层结构是数组,对数组的封装,实现了常用的增删查改等接口。
分类
静态顺序表
概念:使用定长数组存储元素
cpp
#include<stdio.h>
#define N 7;
typedef int SLdatatype;
struct Seqlist
{
SLdatatype a[N];//定长数组
int size; //有效数据个数
};

静态顺序表缺陷:空间少了不够用,给多了造成空间浪费。
动态顺序表
cpp
#include<stdio.h>
typedef int SLdatatype;
typedef struct Seqlist
{//动态顺序表--按需申请
SLdatatype* arr;
int size; //有效数据个数
int capacity;//空间容量
}SL;
动态顺序表的实现
cpp
//初始化和销毁
void SeqListInit(SeqList* ps)
{
ps->a = NULL;
ps->size = ps->capacity = 0;
}
void SeqListDestroy(SeqList* ps)
{
if(ps->a)
free(ps->a);
ps->a = NULL;
ps->size = ps->capacity = 0;
}
cpp
//尾插
void SeqListPushBack(SeqList* ps, SLDateType x)
{
//空间不足时,扩容
if (ps->size == ps->capacity)
{ //当capacity==0时
int newcapacity=ps->capacity==0 ? 4 : 2 * (ps->capacity);
SLDateType* tmp =(SLDateType*) realloc(ps->a, newcapacity *sizeof(SLDateType));
//申请失败时
if (tmp == NULL)
{
perror("realloc fail!");
exit(1);
}
ps->a = tmp;
ps->capacity = newcapacity;
}
//当空间充足时
ps->a[ps->size] = x;
++ps->size;
}

由于后面的很多情况我们都要检查空间是否满了,所以我们直接把检查空间满了的程序提成一个函数
cpp
/检查空间是否足够
void checkifenough(SeqList* ps)
{ //空间不足时,扩容
if (ps->size == ps->capacity)
{ //当capacity==0时
int newcapacity = ps->capacity == 0 ? 4 : 2 * (ps->capacity);
SLDateType* tmp = (SLDateType*)realloc(ps->a, newcapacity * sizeof(SLDateType));
//申请失败时
if (tmp == NULL)
{
perror("realloc fail!");
exit(1);
}
ps->a = tmp;
ps->capacity = newcapacity;
}
}
尾插就可以改进成
cpp
//尾插
void SeqListPushBack(SeqList* ps, SLDateType x)
{
assert(ps);
checkifenough(ps);
//当空间充足时
ps->a[ps->size] = x;
++ps->size;
}
时间复杂度O(1)
cpp
//头插
void SeqListPushFront(SeqList* ps, SLDateType x)
{
assert(ps);
checkifenough(ps);
for (int i = ps->size; i >= 1; i--)
{
ps->a[i] = ps->a[i-1];
}
ps->a[0] = x;
(ps->size)++;
}
时间复杂度O(n)
cpp
//头删
void SeqListPopFront(SeqList* ps)
{
assert(ps&&ps->a);//顺序表不能为空
for (int i = 0; i < (ps->size - 1); i++)
{
ps->a[i] = ps->a[i + 1];
}
(ps->size)--;
}
时间复杂度O(n)
cpp
//尾删
void SeqListPopBack(SeqList* ps)
{
assert(ps && ps->a);//顺序表不能为空
(ps->size)--;
}
时间复杂度O(1)
cpp
//查找,找到了返回下标,没找到,返回-1
int SeqListFind(SeqList* ps, SLDateType x)
{
assert(ps && ps->a);
for (int i = 0; i < ps->size; i++)
{
if (ps->a[i] == x)
return i;
}
return -1;
}
cpp
//顺序表在pos位置前插入x
void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
checkifenough(ps);
for (int i = ps->size; i >= pos + 1; i--)
{
ps->a[i] = ps->a[i - 1];
}
ps->a[pos] = x;
ps->size++;
}
cpp
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos)
{
assert(ps && ps->a);
assert(pos >= 0 && pos <ps->size);
for(int i=pos;i<ps->size-1;i++)
{
ps->a[i] = ps->a[i + 1];
}
ps->size--;
}