超详细!!!顺序表的实现

news2024/12/23 3:51:24

顺链表的实现

  • 顺序表的概念及结构
    • 概念
    • 顺序表与数组的区别
    • 顺序表的结构
  • 动态顺序表的实现
  • 头文件 "SeqList.h"
    • 定义结构体 SL
  • 源文件
    • 顺列表的实现
      • 初始化顺列表 void SLInit(SL* ps)
      • 检查顺列表空间大小 void SLCheckCapacity(SL* ps)
      • 尾插数据 void SLPushBack(SL* ps,SLDataType x)
      • 头插数据 void SLPushFront(SL* ps, SLDataType x)
      • 打印顺序表 void SLPrint(SL* ps)
      • 数组指定位置插入 void SLInsert(SL* ps, int pos, SLDataType x)
      • 销毁顺列表 void SLDestroy(SL* ps)
    • 测试插入
      • 判断有效数据的存在 bool SLIsEmpty(SL* ps)
      • 头删数据 void SLPopFront(SL* ps)
      • 尾删数据 void SLPopBack(SL* ps)
      • 指定数组下标删除 void SLErase(SL* ps, int pos)
    • 测试删除
      • 判断该数据是否存在 bool SLFind(SL* ps, SLDataType x)
      • 查找并返回数据的位置 int SLFindPos(SL* ps, SLDataType x)
      • 修改数据 void SLRevise(SL* ps, int pos, SLDataType x)
    • 测试查找与修改
        • 结束语

顺序表的概念及结构

概念

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

顺序表与数组的区别

顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接⼝,并且顺序表的存储一定是连续的,只能从头开始连续存储。

顺序表的结构

  • 静态顺序表:
    使用定长数组存储元素,缺点是空间不好分配,空间给少了不够用,给多了造成空间浪费。
  • 动态顺序表:
    与静态顺序表相比,动态顺序表的空间可以自主申请空间,大大改善了静态顺序表空间难以分配的情况。

动态顺序表的实现

头文件 “SeqList.h”

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>

#define SLDataType int

typedef struct SeqList
{
	SLDataType* arr;
	int size;
	int capacity;
}SL;

void SLInit(SL* ps);
void SLDestroy(SL* ps);

void SLPushBack(SL* ps,SLDataType x);
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);
void SLPopBack(SL* ps);

void SLErase(SL* ps, int pos);
void SLInsert(SL* ps, int pos, SLDataType x);

bool SLFind(SL* ps, SLDataType x);
int SLFindPos(SL* ps, SLDataType x);
void SLRevise(SL* ps, int pos, SLDataType x)void SLPrint(SL* ps);
bool SLIsEmpty(SL* ps);

定义结构体 SL

typedef struct SeqList
{
	SLDataType* arr;
	int size;
	int capacity;
}SL;

SLDataType* arr;用来存放顺列表的主体数据,SLDataType是我们利用define宏定义所定义的变量,为以后更好的利用顺序表做准备;
size表示有效数据空间个数;
capacity表示总的数据空间个数;
好,下面让我们一 一实现下面头文件中的函数。

源文件

顺列表的实现

初始化顺列表 void SLInit(SL* ps)

void SLInit(SL* ps)
{
	ps->arr=NULL;
	ps->size=ps->capacity=0;
}

将顺列表置为空的状态。

检查顺列表空间大小 void SLCheckCapacity(SL* ps)

void SLCheckCapacity(SL* ps)
{
	if (ps->capacity == ps->size)
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));
		assert(tmp);
		ps->arr = tmp;
		tmp = NULL;
		ps->capacity = newcapacity;
	}
}

如果满足ps->capacity == ps->size 那么说明空间不足,因为有效数据个数等于总的ps->arr空间存放数据个数,所以这个时候就需要为ps->arr开辟扩展新的空间,一般情况下,空间的扩展倍数是1.5倍或者2倍,这里以2倍为例。

int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;

如果ps->capacity的值为0,我们就不能利用倍数去扩展,而是为他直接开辟空间,所以ps->capacity == 0成立时,放回值为4,否则返回值为ps->capacity

SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));
assert(tmp);
ps->arr = tmp;

新建一个SLDataType*tmp变量防止realloc开辟空间失败,返回空指针而导致ps->arr被置为NULL。

ps->capacity = newcapacity;

最后将新ps->arr的空间大小赋值给ps->capacity

尾插数据 void SLPushBack(SL* ps,SLDataType x)

void SLPushBack(SL* ps,SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	ps->arr[ps->size++] = x;
}

我们在这里只需判断空间大小是否合适,再将数据插入即可,ps->size也要加一。

头插数据 void SLPushFront(SL* ps, SLDataType x)

void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	int i = 0;
	for (i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->size++;
	ps->arr[0] = x;
}

这里先判断空间大小,再将所有数据再数组中向后移动一位,再将所要添加的值x放到数组的首元素地址处,此时ps->size要记得加一。

打印顺序表 void SLPrint(SL* ps)

void SLPrint(SL* ps)
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		printf("%d ",ps->arr[i]);
	}
	printf("\n");
}

游历数组arr逐个打印。

数组指定位置插入 void SLInsert(SL* ps, int pos, SLDataType x)

void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	if (pos < 0 || pos > ps->size)
	{
		printf("输入错误!!!");
		return;
	}
	for (int i = ps->size; i > pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[pos] = x;
	ps->size++;
}

先判断pos值是否输入正确,与顺序表空间是否足够。
这里我们只需要将要插入的数组坐标pos之后的数据向后移动一位,再将要插入的数据x放到arr[pos]即可。
在这里插入图片描述

销毁顺列表 void SLDestroy(SL* ps)

void SLDestroy(SL* ps)
{
	if (ps->arr)
		free(ps->arr);
	ps->arr = NULL;
	ps->capacity = ps->size = 0;
}

if (ps->arr) free(ps->arr);将顺序表内arr所申请空间释放,并将ps->size,ps->capacity置为0.

测试插入

#include"SeqList.h"
int main()
{
	SL s;
	SLInit(&s);
	SLPushBack(&s, 1);
	SLPushBack(&s, 2);//1 2
	SLPushFront(&s, 0);
	SLPushFront(&s, -1);//-1 0 1 2
	SLInsert(&s, 0, -2);//-2 -1 0 1 2
	SLInsert(&s, s.size, 3);//-2 -1 0 1 2 3
	SLInsert(&s, 3, 0);//-2 -1 0 0 1 2 3

	SLPrint(&s);
	SLDestroy(&s);
	return 0;
}

先尾插1,2再头插0,-1 此时顺序表为-1 0 1 2,再将-2插入到arr[0]此时顺序表为-2 -1 0 1 2,再将3插入到arr[5]此时顺序表为-2 -1 0 1 2 3,最后将0插入到arr[3]此时顺序表为-2 -1 0 0 1 2 3,程序运行结果如下:
在这里插入图片描述

判断有效数据的存在 bool SLIsEmpty(SL* ps)

bool SLIsEmpty(SL* ps)
{
	assert(ps);
	return (ps->size == 0);
}

若有效值ps->size0,则返回1.

头删数据 void SLPopFront(SL* ps)

void SLPopFront(SL* ps)
{
	assert(ps);
	assert(!SLIsEmpty(ps));
	int i = 0;
	for (i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

我们在处理头删数据的时候,assert(!SLIsEmpty(ps))先判断是否数据存在,若存在,可以让后面的数据对前面进行覆盖,再让ps->size减一即可,覆盖示意图如下:
在这里插入图片描述

尾删数据 void SLPopBack(SL* ps)

void SLPopBack(SL* ps)
{
	assert(ps);
	assert(!SLIsEmpty(ps));
	ps->size--;
}

我们尾删数据只需判断数据是否可删,若可删,我们也只要将ps->size--即可,因为我们在访问的时候,数组arr从0开始向后访问,而我们利用ps->size限制了arr数组从0访问的距离。

指定数组下标删除 void SLErase(SL* ps, int pos)

void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(!SLIsEmpty(ps));
	for (int i = pos; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

这里我们只需要在满足删除条件的时候,找到pos的位置并将后面的数据向前推移即可,再将ps->size - -

测试删除

#include"SeqList.h"
int main()
{
	SL s;
	SLInit(&s);
	for (int i = 0; i < 8; i++)
	{
		SLPushBack(&s, i);//0 1 2 3 4 5 6 7 
	}
	SLPopBack(&s);
	SLPrint(&s);//0 1 2 3 4 5 6
	SLPopFront(&s);
	SLPrint(&s);//1 2 3 4 5 6
	SLErase(&s, 0);
	SLPrint(&s);//2 3 4 5 6
	SLErase(&s, s.size - 1);
	SLPrint(&s);//2 3 4 5
	SLErase(&s, 1);
	SLPrint(&s);//2 4 5
	SLDestroy(&s);
	return 0;
}

先利用SLPushBack(&s, i)循环十次来添加顺序表数据,在进行测试以上代码运行结果如下:
在这里插入图片描述

判断该数据是否存在 bool SLFind(SL* ps, SLDataType x)

bool SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if(ps->arr[i]==x)
			return true;
	}
	return false;
}

遍历顺序表中的整个数组,若存在则返回true,否则返回false

查找并返回数据的位置 int SLFindPos(SL* ps, SLDataType x)

int SLFindPos(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if(ps->arr[i]==x)
			return i;
	}
	return -1;
}

遍历顺序表中的整个数组,当顺序表中的数组元素与查找值相同时,返回数组此时的下标i,若不存在则返回-1

修改数据 void SLRevise(SL* ps, int pos, SLDataType x)

void SLRevise(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	if (pos >= ps->size && ps < 0)
	{
		printf("输入错误,无法修改\n");
		return;
	}
	ps->arr[pos] = x;
}

先判断pos是否合理,若合理,则通过pos直接进行修改。

测试查找与修改

#include"SeqList.h"
int main()
{
	SL s;
	SLInit(&s);
	for (int i = 0; i < 8; i++)
	{
		SLPushBack(&s, i);//0 1 2 3 4 5 6 7 
	}
	printf("%d\n", SLFind(&s,0));//1
	printf("%d\n", SLFind(&s,7));//1
	printf("%d\n", SLFind(&s,8));//0
	printf("%d\n", SLFindPos(&s, 0));//0
	printf("%d\n", SLFindPos(&s, 3));//3
	printf("%d\n", SLFindPos(&s, 7));//7
	printf("%d\n", SLFindPos(&s, 8));//-1
	printf("修改前:");
	SLPrint(&s);
	SLRevise(&s, SLFindPos(&s, 3), -3);//将3改为-3
	SLRevise(&s, SLFindPos(&s, 7), -7);//将7改为-7
	SLRevise(&s, SLFindPos(&s, 0), 10);//将0改为10
	printf("修改后:");
	SLPrint(&s);
	return 0;
}

运行结果如下:
在这里插入图片描述

结束语

本期是顺序表的基本功能实现,下期小编将为大家带来基于本期的顺序表所实现的可存储通讯录程序的实现。
那么,喜欢请多多关照把!!!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1162224.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java强转实验

不存在继承关系时&#xff0c;强转会出现编译时异常。即&#xff1a;无法将两个不同类型的对象做转换 当存在继承关系时&#xff0c;强转正常。备注&#xff1a;同名字段&#xff0c;类型一致&#xff0c;可以强转替代getset。同名字段&#xff0c;类型不一致&#xff0c;强转会…

网络安全之XSS漏洞

一. 引言 Cross-Site Scripting&#xff08;跨站脚本攻击&#xff09;简称XSS&#xff0c;是一种代码注入攻击。XSS 攻击通常指的是利用网页的漏洞&#xff0c;攻击者通过巧妙的方法注入 XSS 代码到网页&#xff0c;因为浏览器无法分辨哪些脚本是可信的&#xff0c;导致 XSS 脚…

matlab求解时变系统的Riccati矩阵微分方程

对于代数Riccati方程的求解网上能找到很多的资源&#xff0c;matlab也有成熟的函数&#xff0c;但是对于时变系统的Riccati矩阵微分方程&#xff0c;能找到的资料还比较少。 一、求解代数Riccati方程 可以在网上找到很多资料&#xff0c;如 https://blog.csdn.net/m0_622999…

python中有哪些你觉得超级牛的模块?

之前在做数据分析的时候&#xff0c;用过一个自动化生成数据探索报告的Python库&#xff1a;ydata_profiling 一般我们在做数据处理前会进行数据探索&#xff0c;包括看统计分布、可视化图表、数据质量情况等&#xff0c;这个过程会消耗很多时间&#xff0c;可能需要上百行代码…

Linux--线程--互斥锁

1.互斥量 a&#xff09;互斥量&#xff08;mutex&#xff09;从本质上来说是一把锁&#xff0c;一般在主线程中定义一个互斥量&#xff0c;就是定义一把锁。然后根据我们的需求来对线程操作这把锁。 b&#xff09;如果给所有的线程都加上锁了&#xff0c;线程们会去争取内存空…

2018年第三届 美亚杯电子取证 个人赛题解

1 Victor的笔记本电脑己成功取证并制作成法证映像档 (Forensic Image)&#xff0c;下列哪个是其MD5哈希值? (2分) A. FC20782C21751AB76B2A93F3A17922D0 B. 5F1BDEB87EE9F710C90CFB3A0BB01616 C. A0BB016160CFB3A0BB0161661670CFB3 D. 917ED59083C8B35C54D3FCBFE4C4BB0B E. F…

当你在浏览器地址栏输入一个URL后,将会发生的事情?个人笔记

客户端 在浏览器输入 URL 回车之后发生了什么&#xff08;超详细版&#xff09; - 知乎 (zhihu.com) 大致流程是&#xff1a; URL 解析DNS 查询TCP 连接处理请求接受响应渲染页面 1.URL解析 地址解析&#xff1a; 首先判断你输入是否是一个合法的URL还是一个待搜索的关键…

上市公司-供应链效率数据集(2000-2022年)

参照张倩肖&#xff08;2023&#xff09;、Feng&#xff08;2015&#xff09;、张树山&#xff08;2023&#xff09;的做法&#xff0c;团队以库存周转天数来衡量供应链效率 库存周转天数有效克服了因企业保留安全库存而导致供应链效率较低的测算误差&#xff0c;体现供应链上…

回归预测 | Matlab实现POA-CNN-SVM鹈鹕算法优化卷积神经网络-支持向量机多变量回归预测

Matlab实现POA-CNN-SVM鹈鹕算法优化卷积神经网络-支持向量机多变量回归预测 目录 Matlab实现POA-CNN-SVM鹈鹕算法优化卷积神经网络-支持向量机多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.POS-CNN-SVM鹈鹕算法优化卷积神经网络-支持向量机的多变量回归…

好用的CRM软件都有哪些功能?

好用的CRM软件不仅仅是将客户资料存档&#xff0c;更大的作用还在于充分发挥数据的价值提升客户管理效率。如果您了解过多款CRM软件就一定会发现它们的功能都不尽相同&#xff0c;但是好用的CRM工具离不开这些功能&#xff1a; 一、客户视图 客户视图主要由4类数据组成&#…

基于springboot实现游戏分享网站系统项目【项目源码+论文说明】

基于springboot实现游戏分享网站演示 摘要 网络的广泛应用给生活带来了十分的便利。所以把游戏分享管理与现在网络相结合&#xff0c;利用java技术建设游戏分享网站&#xff0c;实现游戏分享的信息化。则对于进一步提高游戏分享管理发展&#xff0c;丰富游戏分享管理经验能起到…

跨境商城源码价格

在当今数字商务的时代&#xff0c;跨境电商已经成为了越来越多企业的选择。然而&#xff0c;要建立一个高效、便捷、全球化的跨境商城并不是一件简单的事情。所幸&#xff0c;现在有一个开源的解决方案&#xff0c;给企业提供了无限的可能性。跨境商城源码价格合乎实际&#xf…

浅谈AcrelEMS-CB商业建筑能源管理系统解决方案-安科瑞 蒋静

1概述 AcrelEMS-CB商业建筑能源管理系统&#xff0c;集电力监控、电能质量监测与治理、电气安全预警、能耗分析、照明控制、新能源使用、能源收费以及设备运维等功能于一体&#xff0c;通过一套系统对商业建筑的能源进行统一监控、统一运维和调度&#xff0c;系统可以通过WEB和…

对比学习(contrastive Learning)

起源和定义 自监督学习又可以分为对比学习(contrastive learning)和生成学习(generative learning)两条主要的技术路线。 比学习的核心思想是将正样本和负样本在特征空间对比&#xff0c;从而学习样本的特征表示&#xff0c;使得样本与正样本的特征表示尽可能接近。正样本和负…

webase编译合约一直转圈卡住解决方案

问题:webase编译合约一直转圈卡住,等再久也没反应 解决方案: 进入webase-web目录,然后进入static\js目录,执行以下命令: curl -#L https://osp-1257653870.cos.ap-guangzhou.myqcloud.com/WeBASE/download/solidity/wasm/v0.4.25.js -o v0.4.25.js curl -#L https://os…

Unity AssetBundle打包

1&#xff0c;AssetBundle的概念与作用 AssetBundle是一个存档文件&#xff0c;是Unity提供的一种用于存储资源的资源压缩包&#xff0c;可以包含模型、贴图、音频、预制体等。 Unity中的AssetBundle系统是对资源管理的一种扩展&#xff0c;通过将资源分布在不同的AB包中可以最…

SpringBoot--Web开发篇:含enjoy模板引擎整合,SpringBoot整合springMVC;及上传文件至七牛云;restFul

SpringBoot的Web开发 官网学习&#xff1a; 进入spring官网 --> projects --> SpringBoot --> LEARN --> Reference Doc. --> Web --> 就能看到上述页面 静态资源映射规则 官方文档 总结&#xff1a; 只要是静态资源&#xff0c;放在类路径下&#xff1…

制作网页版H5页面商城源码系统+随心DIY 带前后端完整搭建教程

随着智能手机的广泛普及&#xff0c;人们越来越依赖手机进行日常生活中的各种活动&#xff0c;包括购物。传统的PC端购物模式已经无法满足人们的需求&#xff0c;因此开发移动端的购物系统势在必行。而现如今H5技术不断发展成熟&#xff0c;使得在手机等移动设备上展示网页版商…

Nginx常见问题解决

一、修改nginx.conf报错 背景&#xff1a;修改nginx.conf&#xff0c;配置转发到tcp的信息&#xff1a; 在stream块中配置转发规则&#xff1a;在stream块中&#xff0c;使用server指令来配置转发规则。例如&#xff0c;如果你要将TCP流量转发到example.com:1234&#xff0c;可…

短视频矩阵营销系统工具如何助力商家企业获客?

1.批量剪辑技术研发 做的数学建模算法&#xff0c;数学阶乘的组合乘组形式&#xff0c;采用两套查重机制&#xff0c;一套针对素材进行查重抽帧素材&#xff0c;一套针对成片进行抽帧素材打分制度查重&#xff0c;自动滤重计入打分。 2.账号矩阵分发开发 多平台&#xff0c;…