首页 > 其他分享 >顺序表实现

顺序表实现

时间:2024-07-12 19:56:17浏览次数:10  
标签:ps 顺序 下标 实现 int data size

顺序表介绍

顺序表是用来连续存放数据单元的一种结构,逻辑连续的两个元素在实际上也为连续的。

顺序表的实现

顺序标定义

由于我们存储多中数据,所以顺序表的定义使用结构体类型。

由于是连续的数据单元,所以我们使用数组来接收顺序表中的数据,size用来表示数据表中存放了多少个数组,capicity用来表示顺序表的容量。

typedef int Seqdata;
typedef struct SeqList
{
	Seqdata *data;
	int size;
	int capicity;
}SL;

顺序表功能的实现

顺序表的功能一定有最基础的增删查改,所以接下来就来实现这些功能。

顺序表初始化

顺序表的初始化,首先断言防止传空指针,然后就需要进行开辟空间,开辟的大小由自己来定,判断是否会开辟失败,如果成功将其capicity赋值开辟的大小,并将size初始化为0,data赋值开辟的空间地址。

void SeqInit(SL* ps)
{
	assert(ps);
	Seqdata* tmp = (Seqdata*)malloc(sizeof(Seqdata)*4);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	ps->capicity = 4;
	ps->size = 0;
	ps->data = tmp;
}
顺序表的扩容

我们在使用顺序表的时候,进行增的操作时,我们就需要检查空间是否已经满了,既然我们需要经常进行这个操作,所以我们将其封装为一个函数。

如果capicity和size相同时,那么就说明空间已经满了,需要进行增容,增容使用realloc函数,增容我们任然需要判断是否增容成功,增容成功后我们需要将capicity重新修改为增容后的大小,由于realloc的特性,如果原地址不够增容,会重新在新的地址进行操作,所以以防万一我们将data赋值扩容的地址。

void check(SL* ps)
{
	assert(ps);
	if (ps->capicity == ps->size)
	{
		Seqdata* tmp = realloc(ps->data, ps->capicity * sizeof(Seqdata) * 2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		ps->capicity *= 2;
		ps->data = tmp;
	}
	return;
}
顺序表的尾增

顺序表的尾增,顾名思义就是在数组为尾部后进行插入,我们需要首先检查空间是否已满,直接将size当作下标赋值,最后记得size++。

void Pushtail(SL* ps, Seqdata data)
{
	check(ps);
	ps->data[ps->size] = data;
	ps->size++;
}
顺序表的尾删

顺序表的尾删,我们需要注意的是我们需要多判断一下顺序表中是否为有数据,如果没有就无法进行删除,当size-1是正好为数组最后的下标,将其赋值为0即可,最后将size--完成操作。

void Poptail(SL* ps)
{
	assert(ps);
	assert(ps->size > 0);
	ps->data[ps->size - 1] = 0;
	ps->size--;
}
顺序表的头增

顺序表实现头增,我们需要判断两种情况,一种为顺序表没有数据,这时候就可以直接将数组第一个元素直接赋值,如果是有元素的情况下,就需要将数据进行搬运从而将数据放入头部。

我们如果搬数据我们有两种方式,一种从前向后遍历,另外一种从后向前遍历。

我们可以试想一下如果从前向后遍历的化,第二个存放第一个的数据,这时第二个的数据已经被修改了,再往后数据就一直为第一个的数据,所以从前向后无法实现头插。

所以使用头插我们需要使用另外一种遍历方式,从后向前。

void Pushhead(SL* ps, Seqdata data)
{
	check(ps);
	if (ps->size == 0)
	{
		ps->data[0] = data;
	}
	else
	{
		int i = 0;
		for (i = ps->size; i >0 ; i--)
		{
			ps->data[i] = ps->data[i - 1];
		}
		ps->data[0] = data;
	}
	ps->size++;
}
顺序表的头删

顺序表的头删既然是删除所以一定要判断顺序表是否为空,顺序表中只有一个数据时,直接将其赋值为0,如果有多个就和头插类似需要从前向后遍历或从后向前遍历。

如果时从后向前,如果是这样的写法就会是数据一直被最后数据覆盖,所以很明显是不行的。

如果是从前向后的化,就可以成功实现。

void Pophead(SL* ps)
{
	assert(ps);
	assert(ps->size>0);
	if (ps->size == 1)
	{
		ps->data[0] = 0;
	}
	else
	{
		int i = 0;
		for (i = 0; i < ps->size-1; i++)
		{
			ps->data[i] = ps->data[i + 1];
		}
	}
	ps->size--;
}
顺序表的销毁

由于我们开辟了空间,那么我们就一定需要进行释放,将空间还给操作系统。

void DestroySeq(SL* ps)
{
	assert(ps);
	free(ps->data);
	ps->data = NULL;
	ps->capicity = 0;
	ps->size = 0;
}
顺序表的查找

我们如果要查找顺序表的数据的话,可以通过size遍历整个数组,如果找到就返回下标,如果没有找到就返回-1。

int Finddata(SL* ps, Seqdata data)
{
	assert(ps);
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (ps->data[i] == data)
		{
			return i;
		}
	}
	return -1;
}
顺序表的下标插入

执行插入操作我们需要输入插入的下标,插入的下标我们可以断言一下,插入的下标不能为负数也不能超过最后一个数据的下标,分情况讨论,如果没有数据的话且输入下标为0就直接给第一个元素赋值,其他的我们可以模仿头插的方式来搬运数据,结束条件为大于传来的下标。

void SLInsert(SL* ps, int pos, Seqdata data)
{
	assert(pos >= 0&&pos<=ps->size);
	check(ps);
	if (ps->size == 0)
	{
		ps->data[0] = data;
	}
	else
	{
		int i = 0;
		for (i = ps->size; i > pos; i++)
		{
			ps->data[i] = ps->data[i - 1];
		}
		ps->data[pos] = data;
	}
	ps->size++;
}

顺序表的下标删除

顺序表要进行下标删除时,因为是删除,所以一定要判断是否有数据,分情况讨论,如果只有一个直接将其赋值为0即可,如果要删掉的下标为最后一个的话,可以直接将最后一个数组元素置为0,剩下的进行删除时模仿头删的方式来搬运数据,从而实现删除。

void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	int end = ps->size - 1;
	int i = 0;
	if (ps->size == 1)
	{
		ps->data[0] = 0;
	}
	else if (end == pos)
	{
		ps->data[end] = 0;
	}
	else
	{
		for (i = pos; i < end; i++)
		{
			ps->data[i] = ps->data[i + 1];
		}
	}
	ps->size--;
}
顺序表的打印

顺序表打印我们可以使用遍历的方式使其依次打印,同样也要判断顺序表是否为空。

void SLpint(SL* ps)
{
    assert(ps);
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->data[i]);
	}
}

结语

顺序表在编写时要注意申请的空间及时释放,并且要注意传入的数据是否可行,如果不行会造成越界等问题记得在开始就将其断言,希望我的这篇文章对你有所帮助。

标签:ps,顺序,下标,实现,int,data,size
From: https://blog.csdn.net/m0_73736626/article/details/140385889

相关文章

  • 【Unity】碰撞检测算法及框架实现
    背景硕士期间研究课题是海洋生物数字孪生,基于各类Boids改进的算法里会有大量的海洋鱼类在三维空间中运动,鱼类之间会有互相感知的过程,同一帧里需要对许多行为进行决策判定,例如同伴鱼、食物、捕食者、栖息地等等。因此打算研究下有什么空间加速算法能够避免暴力迭代,减少开销。既然......
  • MyBatis用嵌套ResultMap实现一对多映射
    背景我们知道,MyBatis可以很方便地把SQLselect出来的数据直接映射为对象的属性,把对象取出来。但是,有些对象的属性是集合类型,集合里保存的是数个其他类型的对象。如何用MyBatis把它取出来呢?例子以以下这个应用场景为例:一个教师对应多个课程。数据结构如下:publicclassCour......
  • 在 PostgreSQL 里如何实现数据的分布式查询的负载均衡?
    文章目录在PostgreSQL中实现数据分布式查询的负载均衡在PostgreSQL中实现数据分布式查询的负载均衡在当今数字化时代,数据量呈爆炸式增长,对于大规模数据处理的需求也日益迫切。在PostgreSQL中实现数据的分布式查询负载均衡成为了提升系统性能和可用性的关键......
  • Redis的哨兵和集群实现高可用
    一个典型的高可用Redis集群示例配置1个主服务器2-3个从服务器3-5个哨兵哨兵和集群就是为了高可用哨兵哨兵的功能:监听和故障转移(1)客户端可以从哨兵获得集群的状态。(2)当主服务器断开,哨兵可以进行选举主服务器。哨兵的工作流程在配置中,设置master的ip和端口创建maste......
  • 用Vue3和Plotly.js实现3D小提琴图的交互式可视化
    本文由ScriptEcho平台提供技术支持项目地址:传送门小提琴图:绘制性别账单分布应用场景小提琴图是一种数据可视化工具,用于比较不同组别的分布。它结合了箱线图和核密度估计,可以直观地展示数据的中心趋势、离散度和分布形状。小提琴图常用于比较不同性别、年龄组或其他类别......
  • react 实现前端发版监测
    先说下前端发版流程1.前端打包输出产物/dist文件2.删除远程服务下打包的旧代码3.将打包参物/dist文件copy到远程服务器目录4.重启服务器问题1在步骤2,3,4中用户访问目标服务器会报JS错误,正常情况打开网页的控制面板会看下报错信息`Failedtofetchdynamicallyimp......
  • 51单片机:实现CSGO中C4下包功能(附功能实现视频和代码详解)
    目录一、功能实现二、功能简介1.矩阵键盘输入密码2.S11确认输入密码3.启用蜂鸣器三、模块化代码1.Buzzer.h2.Buzzer.c3.MatrixKey.h4.MatrixKey.c5.LCD1602.h6.LCD1602.c7.Delay.h8.Delay.c四、主函数五、Keil5界面一、功能实现51单片机实现CSGO中C4下包......
  • 使用VGG16和MLP实现猫狗图像识别
    数据集数据集可以参考我之前那篇文章,取一部分数据每个300条即可:基于卷积神经网络(CNN)的猫狗图像分类系统实现-CSDN博客1.目的使用VGG16的结构提取图像特征,再根据特征建立MLP模型,实现猫狗图像识别。训练/测试数据:data 1.对数据进行分离、计算测试数据准确率 2.使用VGG1......
  • 在网页中实现截屏粘贴的功能
    <!DOCTYPEHTML><htmllang="en-US"><head><metacharset="UTF-8"><title>利用clipboardData在网页中实现截屏粘贴的功能</title><styletype="text/css">#box{width:200px;height:200px;border:1pxsol......
  • UWA学堂上新|服务器AOI(Area Of Interest)算法和功能实现
    课程是《基于.NetCore开发MMORPG分布式游戏服务器》系列课程第6节,本系列课程旨在帮助大家从零开始搭建商业化MMORPG的分布式服务器框架,包括不同种类服务器的线程模型,如中心服务器、网关服务器、游戏服务器、寻路服务器等,并讲解了这些服务器该如何根据各自的职责进行业务模块分工......