一篇博客读懂顺序表 —— Sequence-List

目录

一、顺序表的初始定义

1.1新建头文件和源文件

1.2 SeqList.h 中的准备工作

二、顺序表的初始化与销毁

三、首尾插入元素

四、首尾删除元素

五、中间插入元素

六、中间删除元素

 七、查找指定元素下标

八、源代码


一、顺序表的初始定义

1.1新建头文件和源文件

当我们要实现通讯录时,我们会自定义一个 contact.h 文件来存储我们的各种声明,自定义一个 contact.c 文件来存储实现声明的函数,同时还会存在一个 test.c 来测试我们代码的可行性。

在这里我们学习顺序表时,也要使用这种方式,来分割我们的代码使程序更加简洁耐看:

在 SeqList.h 中,我们要声明我们需要的头文件、重新定义的类型、我们需要的函数...... 

1.2 SeqList.h 中的准备工作

为了方便我们修改顺序表中的数据类型,我们把我们顺序表中的类型(int为例)重定义为SLDataType,这样如果我们以后想修改数据类型的话,可以直接来此处将 int 改为 double......

typedef int SLDataType;

 其次,我们定义的顺序表其实是一个结构体,其包含了一个表头(一个指针),实际保存的数据以及表的容量,这里我们并把结构体名称重定义为简称,方便后续的使用。

typedef struct SeqList
{
	int* p;//表头
	int size;//实际存储的数据数量
	int capacity;//此时表中的容量
}SL;

我们的顺序表要具有哪些特点呢?

1.动态存储,可以动态开辟使用空间

2.各种位置的增删查改,分为头、尾、中间。 

二、顺序表的初始化与销毁

初始化和销毁:

首先用断言来保证传入的指针不为空,其次我们需要用 SLInit 函数来将结构体中的数据一一赋初值,其次在销毁数据时,也要保证 free 函数的对象为非空指针,接着将数据重新初始化。

void SLInit(SL* psl) //初始化顺序表
{
	assert(psl != NULL);
	psl->p = NULL;
	psl->size = 0;
	psl->capacity = 0;
}
void SLDestroy(SL* psl) //销毁顺序表
{
	assert(psl != NULL);
	if (psl->p != NULL)
	{
		free(psl->p);
		psl->size = 0;
		psl->capacity = 0;
	}
}

因为我们的顺序表是动态开辟空间,所以写一个检查实时容量的函数是必备的,在此处我们使用二倍扩容的方法来开辟内存空间,但是在初始化时我们把我们的 capacity 赋值为 0,在进行二倍扩容时还是 0,这时就可以用三目运算符完美规避这个问题。

检查并扩充容量:

并且我们用新的临时变量来保存扩容后的空间,在没有问题后再把值返回给原本的变量。

void SLCheckCapacity(SL* psl)
{
	assert(psl != NULL);
	if (psl->size == psl->capacity)
	{
        //因为初始化时capacity为0,所以我们按照二倍扩容后也是0,这里运用三目运算符就能很好的解决
		SLDataType NewCapacity = (psl->capacity == 0) ? 4 : psl->capacity * 2;
        //动态开辟的空间是给顺序表的,注意不要把改行上下两个数据颠倒
        //sizeof() 不要忘!!
		SLDataType* tmp = (SLDataType*)realloc(psl->p, sizeof(SL) * NewCapacity);
		if (tmp == NULL)
		{
			perror("SLCheckCapacity -> realloc");
			return;
		}
		psl->capacity = NewCapacity;
		psl->p = tmp;
	}
}

三、首尾插入元素

打印顺序表:

 为了更好的测试我们的代码,我们可以先写一个打印函数来打印我们的顺序表。

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

尾部插入元素:

void SLPushBack(SL* psl, SLDataType x)
{
	assert(psl != NULL);
	SLCheckCapacity(psl);//检查是否需要扩容
	psl->p[psl->size] = x;
	psl->size++;
}

首部插入元素:

首部插入元素就比尾部插入元素复杂一点啦,我们需要让前面的元素覆盖后面的元素,下图我们模拟顺序表中有 8 个元素(size == 8),来看一下我们的代码应该如何写:

我们让 i 从后面开始向前走,才能保证有用的元素不会被覆盖,同时我们根据首尾元素的覆盖下标推理出 i 的取值范围。

//第一种取值
void SLPushFront(SL* psl, SLDataType x)
{
	assert(psl != NULL);
	SLCheckCapacity(psl);
	int i = psl->size;
	for (; i > 0; i--)
	{
		psl->p[i] = psl->p[i - 1];
	}
	psl->p[0] = x;
	psl->size++;
}

//第二种取值
void SLPushFront(SL* ps, SLDateType x)//ʱ临Ӷ O(n) ;  n O(n^2)
{
	assert(ps != NULL);
	SLCheckCapacity(ps);
	int i = ps->size - 1;
	for (; i >= 0; i--)
	{
		ps->p[i + 1] = ps->p[i];
	}
	ps->p[0] = x;
	ps->size++;
}

四、首尾删除元素

尾部删除元素:

这里我们采用 size-- 的方法,让我们直接无法访问到最后一个元素,下一次增添时又会被新的元素覆盖以实现删除的操作,同时断言我们的实际元素个数必须多余 0

void SLPopBack(SL* psl)
{
	assert(psl != NULL);
    assert(psl->size > 0);
	psl->size--;
}

首部删除元素: 

void SLPopFront(SL* psl)
{
	assert(psl != NULL);
	int i = 1;
	for (; i <= psl->size; i++)
	{
		psl->p[i - 1] = psl->p[i];
	}
	psl->size--;
}

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

五、中间插入元素

void SLInsert(SL* psl, int num, SLDataType x)
{
	assert(psl != NULL);
	assert(num >= 0 && num <= psl->size);
	SLCheckCapacity(psl);
	int i = psl->size - 1;
	for (; i >= num; i--)
	{
		psl->p[i + 1] = psl->p[i];
	}
	psl->p[num] = x;
	psl->size++;
}

六、中间删除元素

void SLErase(SL* psl, int num)
{
	assert(psl != NULL);
	assert(num >= 0 && num < psl->size);
	SLCheckCapacity(psl);
	int i = num;
	for (; i < psl->size - 1; i++)
	{
		psl->p[i] = psl->p[i + 1];
	}
	psl->size--;
}

 七、查找指定元素下标

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

八、源代码

欢迎光临我的Gitee - Gitee.comicon-default.png?t=N7T8https://gitee.com/bright-and-sparkling-at-night/studying/commit/dd1f9978f81f9decce01805623b4708b7671f3e0

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Swift语言配合HTTP写的一个爬虫程序

下段代码使用Embassy库编写一个Swift爬虫程序来爬取jshk的内容。我会使用proxy_host为duoip&#xff0c;proxy_port为8000的爬虫IP服务器。 使用Embassy库编写一个Swift爬虫程序可以实现从网页上抓取数据的功能。下面是一个简单的步骤&#xff1a; 1、首先&#xff0c;需要在X…

虹科示波器 | 汽车免拆检修 | 2010款江铃陆风X8车发动机怠速抖动、加速无力

一、故障现象 一辆2010款江铃陆风X8车&#xff0c;搭载4G6GS4N发动机&#xff0c;累计行驶里程约为20万km。该车在其他修理厂进行发动机大修&#xff0c;维修后试车&#xff0c;发动机怠速抖动、加速无力。用故障检测仪检测&#xff0c;发动机控制模块&#xff08;ECM&#xff…

JumpServer开源堡垒机与万里安全数据库完成兼容性认证

近日&#xff0c;中国领先的开源软件提供商FIT2CLOUD飞致云宣布&#xff0c;JumpServer开源堡垒机已经与万里安全数据库软件GreatDB完成兼容性认证。针对产品的功能、性能、兼容性方面&#xff0c;经过双方共同测试&#xff0c;万里安全数据库软件&#xff08;简称&#xff1a;…

Vue组件化开发,组件的创建,注册,使用,详解Vue,vm,VueComponent,vc

组件化开发 模块是指将一个大的js文件按照模块化拆分规则进行拆分成的每个js文件, 凡是采用模块方式开发的应用都可以称为模块化应用(组件包括模块) 传统方式开发的一个网页通常包括三部分: 结构(HTML)、样式(CSS)、交互(JavaScript) 关系纵横交织复杂&#xff0c;牵一发动全…

组件与Props:React中构建可复用UI的基石

目录 组件&#xff1a;构建现代UI的基本单位 Props&#xff1a;组件之间的数据传递 Props的灵活性&#xff1a;构建可配置的组件 组件间的通信&#xff1a;通过回调函数传递数据 总结&#xff1a; 组件&#xff1a;构建现代UI的基本单位 组件是前端开发中的关键概念之一。…

如何使用Ruby 多线程爬取数据

现在比较主流的爬虫应该是用python&#xff0c;之前也写了很多关于python的文章。今天在这里我们主要说说ruby。我觉得ruby也是ok的&#xff0c;我试试看写了一个爬虫的小程序&#xff0c;并作出相应的解析。 Ruby中实现网页抓取&#xff0c;一般用的是mechanize&#xff0c;使…

手机转接器实现原理,低成本方案讲解

USB-C PD协议里&#xff0c;SRC和SNK双方之间通过CC通信来协商请求确定充电功率及数据传输速率。当个设备需要充电时&#xff0c;它会发送消息去给适配器请求充电&#xff0c;此时充电器会回应设备的请求&#xff0c;并告知其可提供的档位功率&#xff0c;设备端会根据适配器端…

SpringBoot集成-阿里云对象存储OSS

文章目录 阿里云 OSS 介绍准备工作SpringBoot 集成 OSS 阿里云 OSS 介绍 阿里云对象存储 OSS &#xff08;Object Storage Service&#xff09;&#xff0c;是一款海量、安全、低成本、高可靠的云存储服务。使用 OSS&#xff0c;你可以通过网络随时存储和调用包括文本、图片、…

单行自动横向滚动——css实现

效果 封装组件 <template><div ref"container" class"scroll-area"><divref"content":class"[isScroll ? scroll : no-scroll]":style"{ color: fontColor }">{{ content }}</div></div> &…

【2023-10-31】某钩招聘网站加密参数分析

声明:该专栏涉及的所有案例均为学习使用,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!如有侵权,请私信联系本人删帖! 文章目录 一、前言二、网站分析1.X-S-HEADER参数2.请求参数data3.响应机密值data一、前言 网址: aHR0cHM6Ly93d3cubGFnb3UuY29t…

11.Z-Stack协议栈使用

f8wConfig.cfg文件 选择信道、设置PAN ID 选择信道 #define DEFAULT_CHANLIST 0x00000800 DEFAULT_CHANLIST 表明Zigbee模块要工作的网络&#xff0c;当有多个信道参数值进行或操作之后&#xff0c;把结果作为 DEFAULT_CHANLIST值 对于路由器、终端、协调器的意义&#xff1…

【MySQL索引与优化篇】数据库的设计规范

数据库的设计规范 文章目录 数据库的设计规范1. 范式2. 键和相关属性的概念3. 第一范式4. 第二范式5. 第三范式6. 小结7. 反范式化7.1 概述7.2 反范式的新问题7.3 反范式适用场景 8. 巴斯范式9. 第四范式、第五范式和域键范式 1. 范式 在关系型数据库中&#xff0c;关于数据表…

免费获得临时域名/内网穿透

文章目录 Coplar 介绍Coplar 使用场景Coplar 使用 Coplar 介绍 》官网地址《 官网介绍&#xff1a; cpolar极点云: 公开一个本地Web站点至公网 只需一行命令&#xff0c;就可以将内网站点发布至公网&#xff0c;方便给客户演示。高效调试微信公众号、小程序、对接支付宝网关…

Jmeter之JSR223

一、JSR223组件 JSR是Java Specification Requests的缩写,意思是Java规范提案。JSR已成为Java界的一个重要标准. JSR223其实包含了有好几种组件,但是其用法都是一致的,并且都是执行一段代码&#xff0c;主要分类如下&#xff1a; JSR223 PreProcessor JSR223 Timer JSR223 S…

使用Gorm进行CRUD操作指南

使用GORM在Go中创建、读取、更新和删除记录的逐步教程 在数据库管理中&#xff0c;CRUD操作是应用程序的支柱&#xff0c;它们使数据的创建、检索、更新和删除成为可能。强大的Go对象关系映射库GORM通过抽象SQL语句的复杂性&#xff0c;使这些操作变得轻松。本文将作为您全面指…

基于ASP.NET MVC + Bootstrap的仓库管理系统

基于ASP.NET MVC Bootstrap的仓库管理系统。源码亲测可用&#xff0c;含有简单的说明文档。 适合单仓库&#xff0c;基本的仓库入库管理&#xff0c;出库管理&#xff0c;盘点&#xff0c;报损&#xff0c;移库&#xff0c;库位等管理&#xff0c;有着可视化图表。 系统采用Bo…

Linux学习笔记之二(环境变量)

Linux learning note 1、环境变量1.1、修好PATH环境变量 1、环境变量 环境变量(environment variables)即系统运行的一些环境参数。主要的环境变量有以下这些&#xff1a; PATH&#xff1a;决定了系统查找可执行文件的目录范围。HOME&#xff1a;指定当前用户的主目录路径。U…

vue中的rules表单校验规则使用方法 :rules=“rules“

一、el-form里面必写属性值 :ref"dataForm" // 提交表单时进行校验 :rules"rules" // return 下的校验规则 :model"userForm" // 绑定表单的值 <el-formref"dataForm" // 必写属性值:rules"rules"…

linux下安装Zabbix教程

笔记&#xff1a; 监控设备 对各种设备的统一管理 Esight 了解开源监控工具 eg Promerthos: Zabbix &#xff1a;集中式系统 大型企业 可视化,高大上、 查看日志 安装zibox软件 安装数据库 进入数据库 进入Zabbox 密码 password 账号Admin 密码zabbix 解决乱码问题 将…

在Spring Boot中使用国产数据库连接池Druid

在我们实际开发过程中&#xff0c;我们经常使用的是DriverManager来获取&#xff0c;通过每次都向数据库建立连接时将Connection加载到内存中&#xff0c;然后验证用户名和密码&#xff0c;这段时间的消耗大致在0.0 5s - 1s左右&#xff0c;每次当我们需要获取数据库连接的时候…