数据结构与算法之美:顺序表详解

news2024/12/27 7:54:17

        Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路!       9673891daefb4c7d9d2343e592a16286.gif

我的博客:<但凡.

我的专栏:《题海拾贝》、《编程之路》、《数据结构与算法之美》

欢迎点赞、关注!

1、 什么是顺序表

        在数据结构中,顺序表是一种基本的数据组织形式,它是线性表的一种实现方式。线性表是由相同数据类型的元素构成的有序序列,而顺序表则是将这些元素顺序地存储在一块连续的存储区域内。顺序表的特点是通过元素的物理位置(内存中的位置)来表示元素之间的逻辑顺序关系。

        其实说白了,数组就是一种顺序表,数组通过开辟一块连续的内存,并将数据连续的存储在这块内存之中。类似这种我们就称之为顺序表。顺序表的底层代码就是数组。

2、顺序表的实现

        现在我们尝试用C语言实现顺序表。

        首先我们想一下,我们想用顺序表实现什么?我们想的是,开辟一块内存,我们可以自由地往里面放数据,也可以自由的从里面删除数据。我们应该还能在顺序表中找到我们想要查找的元素。现在我们就顺着这个思路来写代码。

        需要注意的是,我们在这里写一个头文件,用来声明结构体和函数,然后再写一个实验源文件,用来测试我们的顺序表功能,接着是我们的函数源文件,用来定义函数。以下的各部分代码都是以函数形式呈现的。

2.1结构体的声明

typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a;
	int size;//有效数据数量
	int capacity;//空间大小
}SeqList;

这个结构体声明是放在我们的头文件里的

2.2顺序表的初始化 

void SeqListInit(SeqList* ps)//注意传值和传址问题
{
	ps->a = NULL;
	ps->size =ps->capacity= 0;
}

我们将传入函数的结构体的地址进行初始化。

2.3检查并扩容函数

        在进行插入的时候我们需要先判断一下空间是否足够,如果没开辟空间那就开辟,如果空间满了那就继续开辟,开辟大小为当前大小的两倍:比如现在有四个字节的大小,扩容后为八个字节,当前八个字节扩容后为16个字节(通过概率学分析这样扩容最高效)。

void SLCheckcapacity(SeqList* ps)//检查并扩容
{
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDateType* tmp = (SLDateType*)realloc(ps->a, newcapacity * sizeof(int));
		assert(tmp);
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
}

2.4顺序表数据的插入

(1)尾插

        从顺序表的最后插入就叫尾插。

void SeqListPushBack(SeqList* ps, SLDateType x)//x为插入的数据
{
	SLCheckcapacity(ps);
	ps->a[ps->size++] = x;
}

(2)头插

        从顺序表的最开始插入就叫头插。

void SeqListPushFront(SeqList* ps, SLDateType x)//头插
{
	SLCheckcapacity(ps);
	int i = 0;
	for (i = 0;i < ps->size;i++)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[0] = x;
	++ps->size;
}

        我们可以分析一下,头插时间复杂度为O(n),尾插时间复杂度为O(1)。

2.5顺序表数据的删除

(1)尾删

void SeqListPopBack(SeqList* ps)
{
	assert(ps && ps->size);//顺序表不为空,删除时注意
	--ps->size;
}

(2)头删

void SeqListPopFront(SeqList* ps)//头删
{
	assert(ps && ps->size);//顺序表不为空,删除时注意
	int i = 0;
	for (i = 0;i < ps->size - 1;i++)
	{
		ps->a[i] = ps->a[i+1];
	}
	--ps->size;//别忘了
}

2.6查找

int SeqListFind(SeqList* ps, SLDateType x)//查找
{
	int i = 0;
	for (i = 0;i < ps->size;i++)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return 0;//没找到
}

2.7指定下标插入

void SeqListInsert(SeqList* ps, int pos, SLDateType x)//pos是下标
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckcapacity(ps);//只要是插入我就得判断空间是否足够
	int i = 0;
	for (i = pos;i<ps->size;i++)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[pos] = x;
	++ps->size;
}

2.8指定下标删除

void SeqListErase(SeqList* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	int i = 0;
	for (i = pos;i < ps->size-1;i++)
	{
		ps->a[i] = ps->a[i+1];
	}
	--ps->size;
}

2.9销毁顺序表

void SeqListDestroy(SeqList* ps)
{
	if (ps->a)
	{
		free(ps->a);
	}
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}

        现在我们把这些函数声明在头文件中:

#include <stdlib.h>
typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a;
	int size;//有效数据数量
	int capacity;//空间大小
}SeqList;
//声明函数
// 对数据的管理:增删查改 
void SeqListInit(SeqList* ps);//初始化顺序表
void SeqListDestroy(SeqList* ps);//销毁顺序表

void SeqListPrint(SeqList* ps);
void SeqListPushBack(SeqList* ps, SLDateType x);//尾插
void SeqListPushFront(SeqList* ps, SLDateType x);//头插
void SeqListPopFront(SeqList* ps);//头删
void SeqListPopBack(SeqList* ps);//尾删

// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDateType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos);

        再在测试源文件里引用这个头文件,我们对顺序表进行测试使用:

#include"SeqList.h"
int main()
{
	SeqList ps;
	SeqListInit(&ps);//初始化
	SeqListPushFront(&ps, 5);//实验头插
	printf("%d", ps.a[0]);
	SeqListDestroy(&ps);
}

输出结果:

055424c62cf2441a9e319774bdbc83ea.png

        我们这里只举例使用一下头插,其他的使用都很相似。

        好了,今天的内容就分享到这,我们下期再见!

 

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

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

相关文章

Neo4j 图数据库安装与操作指南(以mac为例)

目录 一、安装前提条件 1.1 Java环境 1.2 Homebrew&#xff08;可选&#xff09; 二、下载并安装Neo4j 2.1 从官方网站下载 2.1.1 访问Neo4j的官方网站 2.1.2 使用Homebrew安装 三、配置Neo4j 3.1 设置环境变量(可选) 3.2 打开配置文件(bash_profile) 3.2.1 打开终端…

Linux centOS 7 安装 rabbitMQ

1.安装前需要了解&#xff0c;rabbitmq安装需要先安装erlang&#xff0c;特别注意的是erlang与rabbitmq的版本之间需要匹配。 el/7/rabbitmq-server-3.10.0-1.el7.noarch.rpm - rabbitmq/rabbitmq-server packagecloud 3.10版本的rabbitmq 对于erlang的版本要求可以看此连接…

SpringBoot整合Mockito进行单元测试超全详细教程 JUnit断言 Mockito 单元测试

Mock概念 Mock叫做模拟对象&#xff0c;即用来模拟未被实现的对象可以预先定义这个对象在特定调用时的行为&#xff08;例如返回值或抛出异常&#xff09;&#xff0c;从而模拟不同的系统状态。 导入Mock依赖 pom文件中引入springboot测试依赖&#xff0c;spring-boot-start…

QT 中 sqlite 数据库使用

一、前提 --pro文件添加sql模块QT core gui sql二、使用 说明 --用于与数据库建立连接QSqlDatabase--执行各种sql语句QSqlQuery--提供数据库特定的错误信息QSqlError查看qt支持的驱动 QStringList list QSqlDatabase::drivers();qDebug()<<list;连接 sqlite3 数据库 …

微信小程序配置less并使用

1.在VScode中下载Less插件 2.在微信小程序中依次点击如下按钮 选择 从已解压的扩展文件夹安装… 3.选中刚在vscode中下载安装的插件文件 如果没有修改过插件的安装目录&#xff0c;一般是在c盘下C:\用户\用户名.vscode\extensions\mrcrowl.easy-less-2.0.2 我的路径是&#xf…

ClouderaManager 集群搭建

前提&#xff1a;服务器之前做过域名映射、免密登录 ClouderaManager 集群 1. 组件分布规划 服务器服务器h1zk、hdfs(dn)、yarn(nm)、spark、kafka、flumeh2hdfs(nn-standy)、yarn(rm-active)、sparkh3hdfs(nn-active)、yarn(rm-standy)、hive、sparkh4zk、hdfs(dn)、yarn(n…

OpenHarmony-3.HDF框架(2)

OpenHarmony HDF 平台驱动 1.平台驱动概述 系统平台驱动框架是系统驱动框架的重要组成部分&#xff0c;它基于HDF驱动框架、操作系统适配层(OSAL, operating system abstraction layer)以及驱动配置管理机制&#xff0c;为各类平台设备驱动的实现提供标准模型。 系统平台驱动(…

Guiding a Diffusion Model with a Bad Version of Itself

Guiding a Diffusion Model with a Bad Version of Itself Abstract1. Introduction2. Background3. Why does CFG improve image quality?Score matching leads to outliers.CFG 消除异常值Discussion 4 Our method Abstract 在图像生成扩散模型中&#xff0c;主要关注的轴心…

Tomcat,javaweb, servlet , springBoot

在server.xml里配置服务器 <scope>provided</scope>打包的时候&#xff0c;这个jar包不会被打进去&#xff0c;因为tomcat已将封装了这个jar包&#xff0c;没必要要这个

D614 PHP+MYSQL +失物招领系统网站的设计与现 源代码 配置 文档

失物招领系统 1.摘要2. 系统开发的背景和意义3.功能结构图4.界面展示5.源码获取 1.摘要 随着互联网的迅速发展&#xff0c;人们的生产生活方式逐渐发生改变&#xff0c;传统的失物招领也可以通过网络处理。本网站是基PHP技术的一款综合性较强的西南民族大学PHP失物招领系统。 …

单总线one-Wire

单总线one-Wire 概述 One-Wire总线是DALLAS公司研制开发的一种协议 特点&#xff1a; 它是由一个总线主节点&#xff0c;一个或多个从节点组成系统&#xff0c;通过一根信号线对从芯片进行数据的读取 每一个符合One-Wire协议的从芯片都有一个唯一的地址&#xff0c;包括48位的…

【llm】——香橙派AIPRO跑qwen2.5-0.5B

qwen2在Ascend310B4上的评测 代码/模型&#xff1a;https://github.com/chenjun2hao/qwen-ascend-llm 依赖 香橙派AIPRO&#xff1a;http://www.orangepi.cn/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-AIpro.htmlCANN8.0&#xff08;自己手动安装的&#…

Android 单元测试断言校验方法 org.junit.Assert

判断布尔值 assertTrue assertFalse 判断对象非空 assertNull(object); 案例&#xff1a; PersistableBundle result Util.getCarrierConfig(mockContext, subId);assertNull(result); 判断是否相等 assertEquals("mocked_string", result.toString()); package or…

Flink 中双流 Join 的深度解析与实战

目录 一、Join 算子 一&#xff09;语义与特性 二&#xff09;通用用法 三&#xff09;不同窗口类型表现 滚动窗口 Join 滑动窗口 Join 二、CoGroup 算子 一&#xff09;功能特点 二&#xff09;通用用法与连接类型实现 内连接&#xff08;InnerJoin&#xff09; 左…

OpenStack-Glance组件

Glance Glance使用磁盘格式和容器格式基础配置镜像转换 Glance 是 OpenStack 的镜像服务&#xff0c;负责存储、发现和管理虚拟机镜像。它允许用户创建和共享镜像&#xff0c;用于启动虚拟机实例。 Glance 的主要功能 &#xff08;1&#xff09;虚拟机镜像的管理 支持镜像的上…

基于神经网络的弹弹堂类游戏弹道快速预测

目录 一、 目的... 1 1.1 输入与输出.... 1 1.2 隐网络架构设计.... 1 1.3 激活函数与损失函数.... 1 二、 训练... 2 2.1 数据加载与预处理.... 2 2.2 训练过程.... 2 2.3 训练参数与设置.... 2 三、 测试与分析... 2 3.1 性能对比.... 2 3.2 训练过程差异.... 3 四、…

Linux入门攻坚——40、Linux集群系统入门-lvs(1)

Cluster&#xff0c;集群&#xff0c;为了解决某个特定问题将多台计算机组合起来形成的单个系统。 这个单个集群系统可以扩展&#xff0c;系统扩展的方式&#xff1a;scale up&#xff0c;向上扩展&#xff0c;更换更好的主机&#xff1b;scale out&#xff0c;向外扩展&…

威联通-001 手机相册备份

文章目录 前言1.Qfile Pro2.Qsync Pro总结 前言 威联通有两种数据备份手段&#xff1a;1.Qfile Pro和2.Qsync Pro&#xff0c;实践使用中存在一些区别&#xff0c;针对不同备份环境选择是不同。 1.Qfile Pro 用来备份制定目录内容的。 2.Qsync Pro 主要用来查看和操作文…

Docker单机网络:解锁本地开发环境的无限潜能

作者简介&#xff1a;我是团团儿&#xff0c;是一名专注于云计算领域的专业创作者&#xff0c;感谢大家的关注 座右铭&#xff1a; 云端筑梦&#xff0c;数据为翼&#xff0c;探索无限可能&#xff0c;引领云计算新纪元 个人主页&#xff1a;团儿.-CSDN博客 目录 前言&#…

【Linux操作系统】多线程控制(创建,等待,终止、分离)

目录 一、线程与轻量级进程的关系二、进程创建1.线程创建线程创建函数&#xff08;pthread&#xff09;查看和理解线程id主线程与其他线程之间的关系 三、线程等待&#xff08;回收&#xff09;四、线程退出线程退出情况线程退出方法 五、线程分离线程的优点线程的缺点 一、线程…