目录
一、顺序表
二、顺序表的分类
三、顺序表的实现前期准备
第一步,确定需要的文件
第二步,开始分析
四、顺序表的实现
1.初始化
2.销毁
3.申请空间
4.打印
5.尾插
6.头插
7.尾删
8.头删
9.指定位置之前插入
10.指定位置之前删除
11.查找
五、注意的问题
1.空指针(常常作为野指针)
2.申请空间(忘记)
3.头插、头删、指定位置之前的插入的下标和结束条件
4.查找相等的时候要用
5.记得要传地址,不是传值!!!
【注】要讲顺序表就要知道什么是线性表以及其中的概念,就需要去系统的对数据结构进行学习,本篇这要是讲解如何用c语言实现顺序表的增删查改
一、顺序表
【提前了解】
顺序表是线性表的一种,线性表的物理结构不一定是线性和逻辑结构一定是线性的
顺序表物理和逻辑结构都是线性的
【说明】
顺序表底层就是数组,下面我们做个比喻
数组(快餐) | 顺序表(大饭店) |
洋芋丝 | 豪华金丝 |
通过这个比喻,可以看出顺序表就是数组的一个包装。
二、顺序表的分类
顺序表又分为静态顺序表和动态顺序表
静态顺序表 | 动态顺序表 | |
---|---|---|
优点 | 固定空间 | 灵活多变 |
缺点 | 1.给多了浪费空间 2.给少了不够用 | 容易导致内存紧张 (需释放空间) |
静态顺序表
//#define Emax 100//定义一个最大值
//
//struct SqeList
//{
// int arr[Emax];//数组
// int size;//有效数据
//};
动态顺序表
typedef int Datatype;//定义一个数据类型,
typedef struct SqeList
{
Datatype* arr;//数组
int size;//有效数据
int capacity;//空间大小
}SL;//结构体变量名
【观察】
- 动态顺序表笔静态多一个空间大小的变化,所以我们一般选用动态顺序表来实现顺序表的增删查改。
- typedef int Datatype;//定义一个数据类型,将来可以随时改要增删查改的数据类型
三、顺序表的实现前期准备
不管是快餐还是大饭店,都是要提前准备好
第一步,确定需要的文件
这里需要三个文件
第一个是测试文件,每次写完一个功能就要测试,防止代码写完,处处报错的崩溃感
第二个是顺序表的功能实现文件,在在测试文件调用
第三个事顺序表的头文件,主要是把函数声明和库函数的放在这个文件(也是整个代码的目录,方便查阅代码的功能)
第二步,开始分析
顺序的增删查改说白了就是数组的增删查改,只需要在数组的基础上初始化和销毁
主要实现的功能
//初始化
void SLorigin(SL* ps);
//销毁
void SLdestory(SL* ps);//打印
void Print(SL ps);
//尾插
void SLbackinsert(SL* ps, Datatype x);
//头插
void SLfrontinsert(SL* ps, Datatype x);
//尾删
void SLbackdelete(SL* ps);
//头删
void SLforntdelete(SL* ps);
//指定位置之前插入
void SLbeforeinsert(SL* ps,int pot,Datatype x);
//指定位置之前删除
void SLbeforedelete(SL* ps, int pot);
//查找
int SLFind(SL*ps,Datatype x);
四、顺序表的实现
1.初始化
以下是头文件(类似)
//初始化
void SLorigin(SL* ps);
SL是结构体的变量名,要传地址才能使用,所以用指针 ,之后的都是类似的
这一步就是大饭店开始做宴席时,要把锅碗瓢盆擦干净——(要动态顺序表的arr,size,capacity不能有其他东西)
代码实现:
void SLorigin(SL* ps)
{
ps->arr = NULL;
ps->capacity = ps->size = 0;
}
调试展示:
画图展示:
2.销毁
//销毁
void SLdestory(SL* ps);
这一步就是餐馆里吃完饭后要把碗筷收回洗干净备用——(将顺序表的内存收回)
代码实现:
//销毁
void SLdestory(SL* ps)
{
if (ps->arr != NULL)
{
free(ps->arr);
}
ps->arr = NULL;
ps->capacity = ps->size = 0;
}
调试展示:
画图展示:
3.申请空间
这个就是餐馆的后厨,需要再一个地方把菜炒出来——(顺序表的空间)
这一步我们直接封装成函数,要用时直接调用(谁都可以在这里炒菜)
代码实现:
//申请空间
void SLCheckspace(SL*ps)
{
if (ps->size == ps->capacity)
{
int Newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
Datatype* tmp = (Datatype*)realloc(ps->arr, sizeof(Datatype) * Newcapacity);
if (tmp == NULL)
{
perror("realloc fail");
return 1;
}
ps->arr = tmp;
ps->capacity = Newcapacity;
}
}
这里的增容使用的是realloc,realloc可以动态的增容,让空间不够用时会按照原来的两倍增容
这样的好处是:既不会打断系统的操作,也不会空间紧张。
调试展示:
4.打印
将菜的成品端上餐桌
//打印
void Print(SL ps);
代码实现:
//打印
void Print(SL ps)
{
for (int i = 0; i < ps.size; i++)
{
printf("%d ", ps.arr[i]);
}
printf("\n");
}
画图展示:
5.尾插
宴席上从最后一桌开始上菜——尾插顾名思义就是从数组的最末端开始插入
//尾插
void SLbackinsert(SL* ps, Datatype x);
代码实现:
//尾插
void SLbackinsert(SL* ps, Datatype x)
{
assert(ps);
SLCheckspace(ps);
ps->arr[ps->size] = x;
++ps->size;
}
调试展示:
画图展示:
6.头插
从第一桌开始端菜——从数组下标为0的地方插入
//头插
void SLfrontinsert(SL* ps, Datatype x);
代码实现:
//头插
void SLfrontinsert(SL* ps, Datatype x)
{
assert(ps);
SLCheckspace(ps);
for (int i = ps->size; i>0; i--)
{
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[0] = x;
++ps->size;
}
调试展示:
画图展示:
7.尾删
从餐桌的最后一桌开始收
//尾删
void SLbackdelete(SL* ps);
代码实现:
//尾删
void SLbackdelete(SL* ps)
{
assert(ps);
assert(ps->size);
--ps->size;
}
运行结果:
画图展示:
8.头删
从第一桌开始收
//头删
void SLforntdelete(SL* ps);
代码实现:
//头删
void SLforntdelete(SL* ps)
{
assert(ps);
assert(ps->size);
for (int i = 0; i<ps->size; i++)
{
ps->arr[i] = ps->arr[i + 1];
}
--ps->size;
}
运行结果:
画图演示:
9.指定位置之前插入
谁点的菜上谁桌
//指定位置之前插入
void SLbeforeinsert(SL* ps,int pot,Datatype x);
代码实现:
//指定位置之前插入
void SLbeforeinsert(SL* ps, int pot, Datatype x)
{
assert(ps);
assert(pot >= 0 && pot <= ps->size);
SLCheckspace(ps);
for (int i = ps->size; i>pot; i--)
{
ps->arr[i] = ps->arr[i-1];
}
ps->arr[pot] = x;
ps->size++;
}
运行结果:
画图展示:
10.指定位置之前删除
谁投诉退谁的菜
//指定位置之前删除
void SLbeforedelete(SL* ps, int pot);
代码实现:
//指定位置之前删除
void SLbeforedelete(SL* ps, int pot)
{
assert(ps);
assert(pot >= 0 && pot < ps->size);
SLCheckspace(ps);
for (int i =pot ; i<ps->size-1; i++)
{
ps->arr[i] = ps->arr[i + 1];
}
--ps->size;
}
运行结果:
画图展示:
11.查找
查账本
//查找
int SLFind(SL*ps,Datatype x);
代码实现:
//查找
int SLFind(SL* ps,Datatype x)
{
for (int i = 0; i < ps->size; i++)
{
if (ps->arr[i] == x)
{
return i;
}
}
return -1;
}
运行结果:
五、注意的问题
1.空指针(常常作为野指针)
ps->arr=NULL;
2.申请空间(忘记)
if()
3.头插、头删、指定位置之前的插入的下标和结束条件
for()
4.查找相等的时候要用
(==)