顺序表是一种线性表,线性表是n个具有相同特性的数据元素的有限序列,常见的线性表有:顺序表,链表,栈,队列 👉线性表的逻辑结构:在逻辑上是一条连续的直线。 👉线性表的物理结构:线性表在物理结构上并不是连续的,线性表在物理上存储时通常以数组或链式的结构存储的。
• 顺序表与数组的关系
◦ 顺序表的底层结构就是数组,通过对数组的封装,实现增删查改等功能。
• 顺序表的分类: ◦静态顺序表
//使用定长数组存储数据
typedef int SLDataType;
#define N 10
typedef struct SeqList
{
SLDataType a[N];//定长数组
int size;//有效元素的个数
}SL;
❗️缺点:
空间是死的,短了不够用,长了会造成空间的浪费。
◦动态顺序表
//按需申请
typedef int SLDataType;
typedef struct SeqList
{
SLDataType* arr;//动态数组。动态内存开辟,确定大小之后再去动态申请
int size;//顺序表当前有效元素的个数
int capacity; //顺序表的空间大小
}SL;
顺序表结构的声明
#include<stdio.h>
#include<stdlib.h>//需要动态申请内存的头文件
#include<assert.h>
typedef int SLDataType;
// 动态顺序表 -- 按需申请
typedef struct SeqList
{
SLDataType* a;
int size; // 有效数据个数
int capacity; // 空间容量
}SL;
//初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
//扩容
void SLCheckCapacity(SL* ps);
//头部插⼊删除 / 尾部插⼊删除
void SLPushBack(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);
//指定位置之前插⼊/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
int SLFind(SL* ps, SLDataType x);
实现顺序表的方法
//顺序表的初始化
void SLInit(SL* ps)
{
assert(ps);
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
//顺序表的销毁
void SLDestroy(SL* ps)
{
assert(ps);
if (ps->arr)//如果arr不等于空
{
free(ps->arr);
}
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
//打印顺序表中的数据
void SLPrint(SL* ps)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
printf("%d ",ps->arr[i]);
}
}
//扩容
void SLCheckCapacity(SL* ps)
{
assert(ps);
if (ps->size == ps->capacity)
{
//申请空间
//malloc calloc realloc 因为要涉及增容,所以用realloc
int newcapacity = ps->capacity == 0 ? 4 : 2* ps->capacity ;
SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));//realloc申请的是字节大小,*(SLDtaType)整形大小
if (tmp == NULL)
{
perror("realloc fail");//空间申请失败,报错
exit(1);//直接退出程序,不再继续执行
}
//申请空间成功
ps->arr = tmp;
ps->capacity = newcapacity;
}
}
//顺序表的尾部插入
void SLPushBack(SL* ps, SLDataType x)
{
//温柔的方法
/*if (ps == NULL)
{
return;
}*/
assert(ps);//暴力方法
if(ps->size==ps->capacity)
SLCheckCapacity(ps);
//ps->arr[ps->size] = x;
//ps->size++;
ps->arr[ps->size++] = x;
}
//顺序表的尾删
void SLPopBack(SL* ps)
{
assert(ps);
assert(ps->size);
--ps->size;
}
//顺序表的头插
void SLPushFront(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
for (int i = ps->size; i > 0; i--)
{
ps->arr[i] = ps->arr[i-1];
}
ps->arr[0] = x;
ps->size++;
}
//头删
void SLPopFront(SL* ps)
{
assert(ps);
assert(ps->size);
for (int i = 0; i<ps->size-1; i++)
{
ps->arr[i] = ps->arr[i+1];
}
ps->size--;
}
//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{
assert(ps);
assert(pos>=0 && pos<=ps->size);
//插入数据之前看数据够不够
SLCheckCapacity(ps);
for (int i = ps->size; i > pos; i--)
{
ps->arr[i] = ps->arr[i-1];
}
ps->arr[pos] = x;
ps->size++;
}
//在指定位置删除数据
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
for (int i = pos; i < ps->size-1; i++)
{
ps->arr[i] = ps ->arr[i + 1];
}
ps->size--;
}
//查找顺序表中的数据
int SLFind(SL* ps, SLDataType x)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
if (ps->arr[i] == x)
{
//找到了
return i;
}
}
return -1;
}