目录
顺序表
前言:要想实现顺序表一定要清楚顺序表的底层逻辑就是数组。在顺序表的实现功能中只要我们会插入其他简直太简单了。
我们今天要分享的主要内容是顺序表的实现。大致内容请看图
一.全部代码
//头文件
#include<stdio.h>
//开辟空间需要用到calloc或malloc或realloc
#include<stdlib.h>
#include<assert.h>
typedef int SLDateType;
typedef struct SeqList
{
SLDateType* arr;
//描述数组arr里存储数据的个数
int size;
//描述数组arr的内存大小
int capicty;
}SL;//函数实现
//顺序表初始化
void SLInit(SL* object)
{
object->arr = 0;
object->size = 0;
object->capicty = 0;
}
//顺序表的打印
void Print(SL object)
{
printf("\n");
for (int i = 0; i < object.size; i++)
{
printf("%d ", object.arr[i]);//
}
}
//销毁
void Destory(SL* object)
{
if (object->arr)
{
object->arr = NULL;
}
object->size = 0;
object->capicty = 0;
}
//检查内存
void CheckCapicty(SL* object)
{
//扩容条件
if (object->size == object->capicty) {
int NewCapicty = object->capicty == 0 ? 4 : 2 * object->capicty;
SLDateType* Re = (SLDateType*)realloc(object->arr, sizeof(SLDateType) * NewCapicty);
if (Re == 0)
{
printf("内存开辟失败");
exit(1);
}
object->arr = Re;
object->capicty = NewCapicty;
}
}
//头插
void pophead(SL* object, SLDateType H1)
{
assert(object);
//检查arr容量是否够
CheckCapicty(object);
for (int i = object->size; i > 0; i--)
{
object->arr[i] = object->arr[i - 1];
}
object->arr[0] = H1;
object->size++;
}
//尾插
void popblack(SL* object, SLDateType B1)
{
assert(object);
CheckCapicty(object);
object->arr[object->size] = B1;
object->size++;
}
//指定插入
void popChoice(SL* object, int number1, SLDateType C1)
{
assert(object);
//检查number1的值是否合理
assert(number1 >= 0 && number1 < object->size);
for (int i = object->size; i > number1; i--)
{
object->arr[i] = object->arr[i - 1];
}
object->arr[number1] = C1;
object->size++;
}
//头删
void Delethead(SL* object)
{
assert(object);
for (int i = 1; i < object->size; i++)
{
object->arr[i - 1] = object->arr[i];
}
object->size--;
}
//尾删
void Deletblack(SL* object)
{
assert(object);
object->size--;
}
//指定删除
void DeletChoice(SL* object, int number2)
{
assert(object);
assert(number2 >= 0 && number2 < object->size);
for (int i = number2; i < object->size-1; i++)
{
object->arr[i] = object->arr[i+1];
}
object->size--;
}
//查找
int Find(SL* object, SLDateType F)
{
assert(object);
for (int i = 0; i < object->size; i++)
{
if (object->arr[i] == F)
{
return i;
}
}
return -1;
}
//测试是否写的正确
void test()
{
SL brr;
SLInit(&brr);
pophead(&brr, 1);
pophead(&brr, 11);
pophead(&brr, 19);
pophead(&brr, 13);
Print(brr);
popblack(&brr, 2);
popblack(&brr, 103);
popblack(&brr, 101);
popblack(&brr, 109);
Print(brr);
popChoice(&brr, 1, 10);
Print(brr);
Delethead(&brr);
Print(brr);
Deletblack(&brr);
Print(brr);
DeletChoice(&brr, 1);
Print(brr);
int find = Find(&brr, 11);
if (find > 0)
{
printf("找到了下标是%i", find);
}
else
{
printf("nothing");
}
Destory(&brr);
}
int main()
{
test();
return 0;
}
二.预备工作
1.我们可以把顺序表分为三个内容:SeqList.h(头文件),SeqList.c(实现文件),test.c(测试文件)
a.SeqList.h
把要申明的东西写在一起。
b.SeqList.c
我们要对顺序表SL进行初始化,插入,删除,查找,这些功能可以写成函数,放在SeqList.c
c.test.c:测试我们写的函数是否正确,简而言之就是写函数。
比如
c.test.c
测试函数是否写的正确
三.写码工作(SeqList.h暂且忽略)
1.顺序表的定义
顺序表的底层逻辑是数组,基于这个原理我们编写出如下代码
//我们不知道我们的数组类型会不会变,所以给它一个名字
typedef int SLDateType;
typedef struct Seqlist{
SLDateType* arr;
//描述数组arr里存储数据的个数
int size;
//描述数组arr的内存大小
int capicty;
}SL;
2.顺序表的初始化
a.SeqList.c
//SeqList.c
#include"SeqList.h"
void SLInit(SL* object)
{
object->arr = 0;
object->size = 0;
object->capicty = 0;
}
b.test.c
#include"SeqList.h"
void test()
{
SL brr;
SLInit(&brr);
}
int main()
{
test();
return 0;
}
c.调试看看是否正确
3.顺序表的销毁
为什么要销毁呢,因为当我们使用malloc/calloc/realloc为其开辟空间结束时要把空间还给操作系统
void Destory(SL* object)
{
if (object->arr)
{
object->arr = NULL;
}
object->size = 0;
object->capicty = 0;
}
4.顺序表的插入
a.头插
画画图我们就知道啦
头插代码
void pophead(SL* object, SLDateType H1)
{
assert(object);
//检查arr容量是否够
CheckCapicty(object);
for (int i = object->size; i > 0; i--)
{
object->arr[i] = object->arr[i - 1];
}
object->arr[0] = H1;
object->size++;
}
注意增加减少都要改变size的值
检查容量是否够
代码
void CheckCapicty(SL* object)
{
//是否扩容条件
if (object->size == object->capicty) {//扩大容量,运用三目操作符
int NewCapicty = object->capicty == 0 ? 4 : 2 * object->capicty;//防止扩容失败,之前的数据被影响
SLDateType* Re = (SLDateType*)realloc(object->arr, sizeof(SLDateType) * NewCapicty);
if (Re == 0)
{
printf("内存开辟失败");
exit(1);
}
object->arr = Re;
object->capicty = NewCapicty;
}
}
b.尾插
思想:检查是否扩容然后尾部直接插入
void popblack(SL* object, SLDateType B1)
{
assert(object);
CheckCapicty(object);
object->arr[object->size] = B1;
object->size++;
}
c.指定插入
//指定插入
void popChoice(SL* object, int number1, SLDateType C1)
{
assert(object);
//检查number1的值是否合理
assert(number1 >= 0 && number1 < object->size);
for (int i = object->size; i > number1; i--)
{
object->arr[i] = object->arr[i - 1];
}
object->arr[number1] = C1;
object->size++;
}
5.删除
如果我们学会了头插尾插指定插,这个肯定不在话下
//头删
void Delethead(SL* object)
{
assert(object);
for (int i = 1; i < object->size; i++)
{
object->arr[i - 1] = object->arr[i];
}
object->size--;}
//尾删
void Deletblack(SL* object)
{
assert(object);
object->size--;
}
//指定删除
void DeletChoice(SL* object, int number2, SLDateType C2)
{
assert(object);
assert(number2 >= 0 && number2 < object->size);
for (int i = number2; i < object->size-1; i++)
{
object->arr[i] = object->arr[i+1];
}
object->size--;
}//简直爽歪歪
6.查找
思想:一个个访问,如果是则返回下标,和数组查找相同数一样
int Find(SL* object, SLDateType F)
{
assert(object);
for (int i = 0; i < object->size; i++)
{
if (object->arr[i] == F)
{
return i;
}
}
return -1;
}
OK到这里基本就差不多了,只要学会了插入,剩下的不要太轻松了!此顺序表是动态顺序表,静态顺序表的空间是一定的,不需要开辟空间。