初阶数据结构(3)顺序表

news2025/4/8 7:30:48

在这里插入图片描述

Hello~,欢迎大家来到我的博客进行学习!

目录

  • 1.线性表
  • 2.顺序表
    • 2.1 概念与结构
    • 2.2 分类
      • 2.2.1 静态顺序表
      • 2.2.2 动态顺序表
    • 2.3 动态顺序表的实现
      • 初始化
      • 尾插
      • 头插
      • 尾删
      • 头删
      • 查找
      • 指定位置之前插入数据
      • 删除指定位置的数据
      • 销毁

1.线性表

首先我们需要知道的是,顺序表和链表都属于线性表。线性表是具有相同特性的一类数据结构的集合。

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…

线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。

这里的相同特性我从逻辑结构和物理结构两个方面进行分析。

  • 逻辑结构(一定是线性的):人为想象出来的。
  • 物理结构(不一定是线性的):比如数组在存储空间是连续的,和物理结构上的线性是一样的。

2.顺序表

2.1 概念与结构

概念:顺序表是用⼀段物理地址连续的存储单元(物理结构是线性的)依次存储数据元素的线性结构,⼀般情况下采用数组存储。顺序表的底层结构是数组。
在这里插入图片描述
顺序表和数组的区别?
顺序表的底层结构是数组,对数组的封装,实现了常用的增删改查等接口。
在这里插入图片描述

2.2 分类

2.2.1 静态顺序表

如果顺序表底层是固定的空间大小,我们把它叫做静态顺序表。
实现静态顺序表,需要三个文件:头文件(.h)、源文件(.c)、测试文件(test.c)。

  • 头文件(.h):用来声明一些结构和我们的方法
  • 源文件(.c):方法的具体实现
  • 测试文件(test.c):用于测试

取名为SeqList(Sequence List),意为连续的。
我们可以定义一下静态顺序表的大小N,还需要一个size来定义一下有效数据的个数。同时这里的数据类型可能是各种各样的,使用typedef来解决。当要使用这个结构体的时候,我每次都要加上关键词,感觉麻烦,使用typedef来解决。

SeqList.h

#define N 1000
typedef char SLDataType;
//静态顺序表
typedef struct SeqList {
	SLDataType arr[N];
	int size;//有效数据的个数
}SL;

2.2.2 动态顺序表

如果空间是不固定的,我想要多少,可以去增加,就是动态顺序表。

#define N 1000
typedef char SLDataType;
//动态顺序表
typedef struct SeqList {
	SLDataType* arr;
	int size;//有效数据的个数
	int capacity;//容量大小
}SL;

2.3 动态顺序表的实现

初始化

现在我先进行初始化,参数传一个s,初始化的具体方法在SeqList.c文件中实现。
SeqList.c

#include"SeqList.h"
//初始化
void SLInit(SL s)
{
	s.arr = NULL;
	s.size = s.capacity = 0;
}

在test.c中进行检验。

#include"SeqList.h"
void SLTest()
{
	SL sl;
	SLInit(sl);
}

int main()
{
	SLTest();
	return 0;
}

此时会报错:
在这里插入图片描述
在test.c的sl是实参,在SeqList里面的s为形参。
在这里插入图片描述
我们需要将sl的地址传过去,而不是传值。传值时,改变形参并不能改变实参。在SeqList.c这里我就应该用指针来接收。
改完以后:
SeqList.c

#include"SeqList.h"
//初始化
void SLInit(SL* ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

test.c

#include"SeqList.h"
void SLTest()
{
	SL sl;
	SLInit(&sl);
}

int main()
{
	SLTest();
	return 0;
}

SeqList.h

#include<stdio.h>
#include<stdlib.h>
#define N 1000
typedef int SLDataType;
静态顺序表
//typedef struct SeqList {
//	SLDataType arr[N];
//	int size;//有效数据的个数
//}SL;

//动态顺序表
typedef struct SeqList {
	SLDataType* arr;
	int size;//有效数据的个数
	int capacity;//容量大小
}SL;

//初始化
void SLInit(SL* ps);

调试看看:
在这里插入图片描述
跳出以后,sl里面的部分也初始化了:
在这里插入图片描述

尾插

现在来添加插入数据的功能,顺序表的底层是数组,我可能需要需要在原来数据的末尾、中间、开头插入数据。
首先实现尾插(在顺序表最后一个可插的位置,插入数据)的功能。
在这里插入图片描述
如上图,我有5块空间,里面有3个有效数据。尾插就是在3的后面插入数据。

用SLPushBack这个函数来实现,里面的参数为ps和我们要插入的数据。现在我们需要在顺序表里插入数据,这里有三个成员:arr、size、capacity。size指向的位置刚好就是最后一个有效数据的下一个位置。
在这里插入图片描述
假设空间足够,现在往里面插入一个数据X = 99,直接往3后面放,这里并不需要遍历数据组,往size这个位置放就行,插入完成之后,size++。

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

假设空间不够(此时size和capacity在一个位置),按以上方式插入数据,会越界。就需要对原数组申请空间,,然后再在size位置插入数据,插入后size++。
因而我们需要分情况来写。
在这里插入图片描述
在增容时,我们使用realloc(可以在原数组的基础上进行增加容量)来进行这一操作。如果插一个数据,增加一个容量,没有空间的浪费,但是增容频繁,程序效率低下。如果一次多申请一些,可能会造成空间的浪费。通常,增容是按倍数增加,如2倍、3倍…这里我选择两倍。
在这里插入图片描述
按照以上思路,其实是有漏洞的。

//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	//空间不够,申请空间
	if (ps->size == ps->capacity)
	{
		//空间不够,2倍增容
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, ps->capacity * 2);


	}
	ps->arr[ps->size++] = x;
}

在realloc这里,第二个参数是size_t size单位是字节,ps->capacity * 2 这里改为 ps->capacity * 2 *sizeof(SLDataType)。并看看增容成功没有。但是之前我们初始化那里把capacity初始化为0,现在需要扩容的话,需要先给一个初始值。我这里先给一个SLDestroy函数,在程序结束时释放动态分配的内存,不然程序结束时会出现内存泄漏。
SeqList.c

#include"SeqList.h"
//初始化
void SLInit(SL* ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	if (ps == NULL)
	{
		return;
	}

	//空间不够,申请空间
	if (ps->size == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		//空间不够,2倍增容
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
	ps->arr[ps->size++] = x;
}

// 释放顺序表
void SLDestroy(SL* ps) 
{
	if (ps->arr != NULL) 
	{
		free(ps->arr);  // Free the allocated memory
		ps->arr = NULL;
	}
}

在这里插入图片描述

头插

现在来实现头插。这里也要看空间大小够不够,则可以分装一个方法来判断空间大小够不够。前面的步骤和尾插差不多,只是实现头插时有部分区别。需要把数据整体往后移动,然后再进行插入。在移动的时候,先把后面的数据往后移动,最后把插入的数据放在下标为0的位置。同样在增加完数据之后,size++。
SeqList.c

#include"SeqList.h"
//初始化
void SLInit(SL* ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

void SLcheckCapacity(SL* ps)
{
	//空间不够,申请空间
	if (ps->size == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		//空间不够,2倍增容
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
}

//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	if (ps == NULL)
	{
		return;
	}

	SLcheckCapacity(ps);

	ps->arr[ps->size++] = x;
}

//头插
void SLPushFront(SL* ps, SLDataType x)
{
	if (ps == NULL)
	{
		return;
	}
	SLcheckCapacity(ps);
	//直接头插
	//数据整体向后移动一位
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
	++ps->size;
}

尾删

ps不能传空,删除数据之后,size要 - -。顺序表为空,也不行。这里把最后一个数据弄掉,不是把最后一个数据弄为0,而是可以修改

//尾删
void SLPopBack(SL* ps)
{
	assert(ps&&ps->size>0);

	--ps->size;

}

头删

这里的前提和尾删一样。ps不能传空,删除数据之后,size要 - -。顺序表为空,也不行。我们需要移动数据,下标为零以后的数据,整体向前移动一位

//头删
void SLPopFront(SL* ps)
{
	assert(ps && ps->size > 0);

	--ps->size;
	for (int i = 0; i<ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
}

查找

这里比较简单,遍历顺序表,如果查找到返回下标;如果找不到返回无效下标。

//查找
int SLFind(SL* ps, SLDataType x)
{
	for(int i = 0; i < ps->size; i++)
	{
		if (x == ps->arr[i])
		{
			//找到了,返回下标
			return i;
		}
	}
	//找不到
	return -1;
}

指定位置之前插入数据

这里新增一个参数pos(指定位置)。pos需要有效,pos >= 0 && pos <= ps->size。与之前一样需要判断空间是否足够,插入好之后size++。
假设需要将99这个数据插入3这个位置之前,需要将pos以及之后的数据向后移动一位。
在这里插入图片描述

//指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	//前=:头插
	//后=:尾插
	assert(pos >= 0 && pos <= ps->size);
	SLcheckCapacity(ps);
	for (int i = ps->size - 1; i > pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[pos] = x;
	++ps->size;
}

删除指定位置的数据

同样的size需要减减,指定位置pos必须pos >= 0 && pos <= ps->size。要删除pos位置的数据就需要把pos之后的数据整体向前移。

//删除指定位置的数据
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);

	for (int i = pos;i<ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}

	--ps->size;
}

销毁

动态申请的空间在不用的时候需要销毁。

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

此时,我们对顺序表已经比较理解了。

好了,我们的顺序表的知识就讲到这里。如果文章内容有误,请大佬在评论区斧正!谢谢大家!
在这里插入图片描述

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

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

相关文章

谷歌发布网络安全AI新模型Sec-Gemini v1

谷歌近日宣布推出实验性AI模型Sec-Gemini v1&#xff0c;旨在通过人工智能技术革新网络安全防御体系。该模型由Sec-Gemini团队成员Elie Burzstein和Marianna Tishchenko共同研发&#xff0c;旨在帮助网络安全人员应对日益复杂的网络威胁。 攻防不对称的破局之道 Sec-Gemini团队…

Meta LLaMA 4:对抗 GPT-4o 与 Claude 的开源王牌

2025 年 4 月&#xff0c;Meta 正式发布了 LLaMA 4 系列的首批两款模型。 这两款模型模型分别是&#xff1a;LLaMA 4 Scout 与 LLaMA 4 Maverick&#xff0c;均采用了 专家混合架构&#xff08;Mixture-of-Experts, MoE&#xff09;。 据 Meta 表示&#xff0c;这是首次有 …

企业级 ClickHouse Docker 离线部署实践指南20250407

企业级 ClickHouse Docker 离线部署实践指南 引言 在数据分析与日志处理日益重要的今天&#xff0c;ClickHouse 凭借其高性能、列式存储架构&#xff0c;成为企业在大数据分析中的首选引擎之一。本文基于一位金融行业从业者在离线网络环境中部署 ClickHouse 的真实实践过程&a…

DeepSeek-MLA

MLA 结构 需要缓存 KV 向量共用的压缩隐特征K 向量多头共享的带位置编码的向量 为什么带有位置信息的 Q 向量来自于隐特征向量&#xff0c;而带有位置的 K 向量来自于 H 向量且共享呢&#xff1f; 最好的方法肯定是从H向量直接计算并且不共享&#xff0c;但是会大大增加显存使…

pyTorch-迁移学习-学习率衰减-四种天气图片多分类问题

目录 1.导包 2.加载数据、拼接训练、测试数据的文件夹路径 3.数据预处理 3.1 transforms.Compose数据转化 3.2分类存储的图片数据创建dataloader torchvision.datasets.ImageFolder torch.utils.data.DataLoader 4.加载预训练好的模型(迁移学习) 4.1固定、修改预训练…

vscode Colipot 编程助手

1、登录到colipot&#xff0c;以github账号&#xff0c;关联登录 点击【continue】按钮&#xff0c;继续。 点击【打开Visual Studio Code】&#xff0c;回到vscode中。 2、问一下11? 可以看出&#xff0c;很聪明&#xff0c;一下子就算出来了。 3、帮我们写一个文件&#xf…

1、window 下SDL 下载使用, 测试环境搭建

1. SDL3下载 官网&#xff1a; https://www.libsdl.org/ 点击SDL Releases 或者 SDL GItHub 进入github下载&#xff1a; 因为自己在windows下使用的mingw,所以下载mingw版的&#xff0c;也可以 下载源码自己编译。 2. 项目搭建 这里使用的时mingw vsocde cmake, 可以使…

OpenGL学习笔记(模型材质、光照贴图)

目录 光照与材质光照贴图漫反射贴图采样镜面光贴图 GitHub主页&#xff1a;https://github.com/sdpyy OpenGL学习仓库:https://github.com/sdpyy1/CppLearn/tree/main/OpenGLtree/main/OpenGL):https://github.com/sdpyy1/CppLearn/tree/main/OpenGL 光照与材质 在现实世界里&…

视频分析设备平台EasyCVR打造汽车门店经营场景安全:AI智慧安防技术全解析

一、方案背景 某电动车企业不停爆出维权新闻&#xff0c;支持和反对的声音此起彼伏&#xff0c;事情不断发酵、反转&#xff0c;每天都有新消息&#xff0c;令人目不暇接。车展、车店作为维权事件的高发场所&#xff0c;事后复盘和责任认定时&#xff0c;安防监控和视频监控平…

Hibernate里的对象不同状态和Session的核心方法

临时状态的测试 Student student new Student("张三", "男", 22, new Date()); 以上student就是一个Transient(临时状态),此时student并没有被session进行托管&#xff0c;即在session的缓存中还不存在student这个对象&#xff0c;当执行完save方法后&a…

模型嵌入式部署

背景 自从深度学习大规模应用以来&#xff0c;其中一个应用方向就是将深度学习视觉算法部署到嵌入式平台上&#xff0c;使用NPU推理。虽然已经做了很久的模型部署&#xff0c;但一直都是在公司默默耕耘&#xff0c;为了发展一下自己“边缘部署专家”这个个人品牌&#xff0c;打…

Redlinux(2025.3.29)

1、将你的虚拟机的网卡模式设置为nat模式&#xff0c;给虚拟机网卡配置三个主机位分别为100、200、168的ip地址。(以nmtui命令为例) 2、测试你的虚拟机是否能够ping通网关和dns&#xff0c;如果不能请修改网关和dns的地址。 首先打开虚拟网络编辑器查看NAT设置里的网关IP&…

uni-app项目运行在浏览器、微信开发者工具、mumu模拟器

一、安装HBuilder X 1、下载HBuilder X 官网网址&#xff1a;https://dcloud.io/hbuilderx.html 根据电脑系统下载对应的版本&#xff08;我的电脑是Windows 10&#xff09; 2.安装HBuilder X 直接将HBuilderX.4.61.2025040322-alpha.zip解压到自己想要存放的文件夹中 双击…

2025-04-07 NO.3 Quest3 MR 配置

文章目录 1 MR 介绍1.1 透视1.2 场景理解1.3 空间设置 2 配置 MR 环境2.1 场景配置2.2 MR 配置 3 运行测试 配置环境&#xff1a; Windows 11Unity 6000.0.42f1Meta SDK v74.0.2Quest3 1 MR 介绍 1.1 透视 ​ 透视&#xff08;Passthrough&#xff09;是将应用的背景从虚拟的…

抓wifi无线空口包之Macbook Pro抓包(一)

参考&#xff1a; 在MAC OS上进行Wi-Fi抓包和空中包分析_空口抓包和无线网卡抓包的区别-CSDN博客 WireShark中802.11帧的类型、子类型对照表_wireshark 怎么看disassociate帧和deauthenticate-CSDN博客 一、在macbook pro上&#xff0c;点击option 同时点击右上角wifi 功能&a…

单元测试原则之——不要模拟值对象 (1)

1. 什么是值对象(Value Objects)? 值对象是指那些不可变且仅通过其属性(数据)来定义的对象。它们通常没有复杂的逻辑或行为,主要用于存储和传递数据。例如: ● 字符串(String) ● 数字(Integer, Double) ● 日期(LocalDate, Instant) ● 自定义的简单数据类(如…

版本控制工具——SVN

目录 【版本控制系统】 【SVN概述】 【SVN基本使用】 【解决SVN拉取文件到本地后不显示绿色图标问题】 【版本控制系统】 版本控制系统&#xff08;version control system&#xff09;是一种用于管理文件变更的软件工具&#xff0c;主要用于记录文件的修改历史&#xff0c…

2022第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组(题解解析)

记录刷题的过程、感悟、题解。 希望能帮到&#xff0c;那些与我一同前行的&#xff0c;来自远方的朋友&#x1f609; 大纲&#xff1a; 1、九进制转十进制-&#xff08;解析&#xff09;-简单的进制转化问题&#x1f604; 2、顺子日期-&#xff08;解析&#xff09;-考察日期 3…

【EC200N-CN——Linux驱动移植】问题回顾

【EC200N-CN——Linux驱动移植】问题回顾 1&#xff09;、开发回顾一、问题回顾与解决过程二、核心原理分析1. **USB设备识别的关键&#xff1a;VID/PID**2. **为什么之前不生成ttyUSB节点&#xff1f;**3. **为什么添加PID后就能生成节点&#xff1f;** 三、日志关键信息解读1…

构建k8s下Helm私有仓库与自定义Chart开发指南

#作者&#xff1a;程宏斌 文章目录 自定义helm模板1、开发自己的chare包2、调试chart3、安装chart 自定义helm模板 https://hub.helm.sh/ 1、开发自己的chare包 [rootmaster ~]# helm create mychare //创建一个名为mychare的chare包 [rootmaster ~]# tree -C mychare/ //以…