数据结构—顺序表(如果想知道顺序表的全部基础知识点,那么只看这一篇就足够了!)

        前言:学习完了C语言的基础知识点之后,我们就需要使用我们所学的知识来进一步对存储在内存中的数据进行操作,这时候我们就需要学习数据结构。而这篇文章为数据结构中顺序表的讲解。


✨✨✨这里是秋刀鱼不做梦的BLOG

✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客

那么我们废话不多说,直接开始讲解。

先让我们看一下讲解的大体内容有哪些:

目录

1.初识顺序表

        (1)顺序表的定义

        (2)顺序表的特点

2.顺序表的分类

        【1】静态顺序表

        【2】动态顺序表

3.顺序表的功能

4.顺序表中各种功能的实现

        【1】 初始化顺序表中的数据。

        【2】 打印顺序表中的数据。

        【3】对顺序表进行尾插(末尾插入数据)。

        【4】对顺序表进行尾删(末尾删除数据)。

         【5】对顺序表进行头插(开头插入数据)。

      【6】 对顺序表进行头删(开头删除数据)。

          【7】 对顺序表查找数据。

        【8】对顺序表数据进行修改。

        【9】指定位置插入数据

        【10】删除指定位置数据

        【11】 销毁顺序表。


1.初识顺序表

在了解顺序表的定义之前,我们需要先了解一下什么是线性表:

线性表,全名为线性存储结构。使用线性表存储数据的方式可以这样理解,即“把所有数据用一根线儿串起来,再存储到物理空间中”

在了解完线性表的概念之后,我们在来看顺序表:        

        (1)顺序表的定义

数据结构在内存中的表示通常有两种形式,一种是顺序存储,另一种是链式存储。线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表的数据元素,我们把这种存储形式存储的线性表称为顺序表。

例如,使用顺序表存储集合 {1,2,3,4,5},数据最终的存储状态如图 1 所示:

由上图可知顺序表存储数据同数组非常接近。其实,顺序表存储数据使用的就是数组。       

        (2)顺序表的特点

1.  顺序表的逻辑结构和物理结构是一致的,都是连续的。

2.  顺序表中任意一个数据元素都可以随机存取,所以顺序表是一种随机存取的存储结构。

这样我们就初步的了解了顺序表。

2.顺序表的分类

        从上边我们已经了解到了顺序表存储数据使用的就是数组,而数组又分为了静态数组和动态数组,所以顺序表也顺其自然的分成了静态顺序表和动态顺序表。

我们直接使用代码来看一下两种顺序表的定义:

        【1】静态顺序表

//静态顺序表
#define SLDateType int
#define NUMBER 10
typedef struct SeqList
{
	SLDateType arr[NUMBER];
	int size;
}SL;

由上边的代码我们可以看到,静态顺序表由一个定长的数组和一个 int 类型的变量size组成(size的作用是用来记录该数组中的元素个数)。

        【2】动态顺序表

//动态顺序表
#define SLDateType int
typedef struct SeqList
{
	SLDateType* arr;
	int size;
	int capacity;
}SL;

由上边的代码我们可以看到,动态顺序表是由一个指针(该指针存放一个数组的地址,该数组可以使用一些方法使其长度发生变化),一个 int 类型的变量size(size的作用是用来记录该数组中的元素个数)和一个 int 类型的变量capacity组成(capacity用来记录数组的容量)。

注:当然在日常的使用或者工作中,我们大部分都是使用动态顺序表(相较于静态顺序表更加灵活)来存储数据并使用顺序表的一些功能来对数据进行操作的。

这样我们就了解了顺序表的分类和其它们的定义方式了。

3.顺序表的功能

        顺序表可以大致包含以下几个功能:

1. 初始化顺序表中的数据。

2. 打印顺序表中的数据。

3. 对顺序表进行尾插(末尾插入数据)。

4. 对顺序表进行尾删(末尾删除数据)。

5. 对顺序表进行头插(开头插入数据)。

6. 对顺序表进行头删(开头删除数据)。

7. 对顺序表查找数据。

8. 对顺序表数据进行修改。

9. 指定位置插入数据。

10. 删除指定位置数据。

11. 销毁顺序表。

这里我们只需要大致的了解顺序表又哪些功能就可以,下面我们会对这10个功能进行详细的讲解。

4.顺序表中各种功能的实现  

        接下来我们就开始对顺序表中的几个功能开始进行讲解(使用动态顺序表):

我们首先定义动态顺序表:

//动态顺序表
#define SLDateType int
typedef struct SeqList
{
	SLDateType* arr;
	int size;
	int capacity;
}SL;

        

        【1】 初始化顺序表中的数据。

我们直接使用代码来看一下:

//动态顺序表的初始化
void SLInit(SL* sl)
{
	assert(sl);
	sl->arr = NULL;
	sl->size = 0;
	sl->capacity = 0;
}

初始化顺序表时,我们先将数组长度设置为0(即为NULL,之后添加数据时在扩容),将元素个数和数组长度设置为0。

        【2】 打印顺序表中的数据。

我们直接使用代码来看一下:

//打印数据
void SLPrint(SL* sl)
{
	assert(sl);
	for (int i = 0; i < sl->size; i++)
	{
		printf("%d ", sl->arr[i]);
	}
	printf("\n");
}

 打印数据只需要使用循环变量数组来打印就可以了。

        【3】对顺序表进行尾插(末尾插入数据)。

我们直接使用代码来看一下:

//向数据表的尾部插入数据
void SLPushBack(SL* sl, SLDateType n)
{
	//对传入的指针进行判断,判断是否为空指针
	assert(sl);
	//判断数组是否需要扩容
	if (sl->size == sl->capacity)
	{
		//如果数组容量为0,则设置为5,如果不为0,则扩大为两倍
		int Newcapacity = sl->capacity = 0 ? 5 : 2 * (sl->capacity);
		SLDateType* temp = (SLDateType*)realloc(sl->arr, Newcapacity * sizeof(SLDateType));
		if (temp == NULL)
		{
			perror("realloc is wrong");
			exit(1);
		}
		sl->arr = temp;
		temp = NULL;
		sl->capacity = Newcapacity;
	} 
	//添加数据
	sl->arr[sl->size++] = n;
}

在上边的代码中我们发现,当数组满了之后,我们需要对数组进行扩容之后,在向数组中添加数据。   

  

        【4】对顺序表进行尾删(末尾删除数据)。

我们直接使用代码来看一下:

//删除顺序表尾部数据
void SLPopBack(SL* sl)
{
	//对传入的指针进行判断,判断是否为空指针
	assert(sl);
	//原来的数组中要有数据
	assert(sl->size);
	sl->size--;
}

对顺序表进行尾删的时候,我们根本不需要删除数组末尾的数据,我们只需要将记录元素个数的数减小1,这样我们在使用的时候就不会使用到末尾的数据了。       

         【5】对顺序表进行头插(开头插入数据)。

我们直接使用代码来看一下:

//向顺序表的头部插入数据
void SLPushFront(SL* sl, SLDateType n)
{
	//对传入的指针进行判断,判断是否为空指针
	assert(sl);
	//判断数组是否需要扩容
	if (sl->capacity == sl->size)
	{
		//如果数组容量为0,则设置为5,如果不为0,则扩大为两倍
		int Newcapacity = sl->capacity = 0 ? 5 : 2 * (sl->capacity);
		SLDateType* temp = (SLDateType*)realloc(sl->arr, Newcapacity * sizeof(SLDateType));
		if (temp == NULL)
		{
			perror("realloc is wrong");
			exit(1);
		}
		sl->arr = temp;
		temp = NULL;
		sl->capacity = Newcapacity;
	}
	//将所有的数据都往后移动一位
	for (int i = sl->size; i >=1 ; i--)
	{
		sl->arr[i] = sl->arr[i-1];
	}
	//添加数据
	sl->arr[0] = n;
	sl->size++;
}

在进行对顺序表进行头插的时候,我们也需要判断数组是否可以添加一个数据,并且由于我们是头插,所以要将原来数组中所有的数据都往后移动一位

      【6】 对顺序表进行头删(开头删除数据)。

我们直接使用代码来看一下:

//删除顺序表头部数据
void SlPopFront(SL* sl)
{
	//对传入的指针进行判断,判断是否为空指针
	assert(sl);
	//原来的数组中要有数据
	assert(sl->size);
	//将除了第一个位置的其他位置的元素往前移动一位
	for (int i = 0; i<sl->size-1; i++)
	{
		sl->arr[i] = sl->arr[i + 1];
	}
	sl->size--;
}

将除了第一个位置的其他位置的元素往前移动一位,这样就可以将第一位的数据进行覆盖掉,完成对顺序表进行头删的操作。  

          【7】 对顺序表查找数据。

我们直接使用代码来看一下:

//对顺序表查找数据
int SeqListFind(SL*sl, SLDateType n)
{
	//对传入的指针进行判断,判断是否为空指针
	assert(sl);  
	int i = 0;
	for (i = 0; i < sl->size; i++)
	{
		if (sl->arr[i] == n)
		{
			//找到则返回该值在数组中的下标
			return i;
		}
	}
	//没有查找到则返回-1
	return -1;  
}

我们遍历数组查找想要的数据就可以,如果没有找到,则返回-1。      

        

        【8】对顺序表数据进行修改。

我们直接使用代码来看一下:

//对顺序表数据进行修改
void SeqListModify(SL* sl, int pos, SLDateType x)
{
	//对传入的指针进行判断,判断是否为空指针
	assert(sl);  
	//原来的数组中要有数据
	assert(sl->size > 0);
	//检查pos下标的合法性
	assert(pos >= 0 && pos < sl->size); 
	//修改pos下标处对应的数据
	sl->arr[pos] = x;  
}

总体的思路就是先判断是否可行后将对应位置的数据进行修改。     

        【9】指定位置插入数据

我们直接使用代码来看一下:

//在指定位置插入数据
void SeqInsert(SL* sl, int pos, SeqType n)
{
	//对传入的指针进行判断,判断是否为空指针
	assert(sl);
	//判断指定位置的合理性
	assert(pos >= 0 && pos <= sl->size);
	//判断是否需要扩容
	if (sl->size == sl->capacity)
	{
		int newcapacity = (sl->capacity == 0 ? 5 : 2 * (sl->capacity));
		SeqType* temp = (SeqType*)realloc(sl, newcapacity * sizeof(SeqType));
		if (temp == NULL)
		{
			perror("realloc fail");
			exit(1);
		}
		sl = temp;
		temp = NULL;
		sl->capacity = newcapacity;
	}
	//添加数据
	for (int i = sl->size - 1;i>=pos; i--)
	{
		sl->arr[i + 1] = sl->arr[i];
	}
	sl->arr[pos] = n;
	sl->size++;
}

在指定位置插入数据时,我们需要判断位置的合理性,即是否是在可以插入的位置进行插入,判断完后,我们判断是否需要扩容,判断完后我们进行数据的插入。    

        【10】删除指定位置数据

我们直接使用代码来看一下:

//删除指定位置数据
void SeqListErase(SL* sl, int pos)
{
	//对传入的指针进行判断,判断是否为空指针
	assert(sl);
	//顺序表不能为空
	assert(sl->size > 0);  
	//检查pos下标的合法性
	assert(pos >= 0 && pos < sl->size);  
	//将pos位置后面的数据依次向前挪动一位,完成覆盖
	for (int i = pos + 1; i < sl->size; i++)  
	{
		sl->arr[i - 1] = sl->arr[i];
	}
	//存储的数据-1
	sl->size--;  
}

对于删除指定位置数据,我们只需要将指定位置数据后面的数据全部向前移动一位完成覆盖即可。        

        【11】 销毁顺序表。

我们直接使用代码来看一下:

//销毁顺序表
void SLDelete(SL* sl)
{
	//将创建的数据空间进行回收
	assert(sl);
	if (sl->arr)
	{
		free(sl->arr);
		sl->arr = NULL;
	}
	sl->size = sl->capacity = 0;
}

从上边的代码中我们知道,我们开创的数组的空间是由malloc函数开辟的,所以在使用完顺序表之后要对该空间进行归还。


以上就是顺序表的全部内容了~~~

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

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

相关文章

JS控制元素平滑滚动,页面自动滚动锚点实现

使用 scrollIntoView 实现元素内子元素的平滑滚动&#xff0c; 下面是模拟接口list返回&#xff0c;然后通过按钮切换下一个&#xff0c;页面就会滚动到响应的位置 具体 scrollIntoView 有一些其他参数来配置滚动的具体交换&#xff0c;网上去查即可 备注&#xff1a;下面的代码…

uniapp 编译后分包下静态图片404问题解决方案

如上图官方说明&#xff1a; 在分包下建立一个static文件夹即可&#xff1a; 分包内代码引用图片 <image src"/分包名称/img/图片名称"></image> <image src"/dataView/img/图片名称"></image>

Centos中一些有趣的命令

目录 1.sl 小火车 2. cowsay 会说话的牛 3.toilet/figlet 图形化输出 4.aafire 小火焰 5.linux_logo 显示系统logo 1.sl 小火车 yum install sl 2. cowsay 会说话的牛 yum install cowsay 3.toilet/figlet 图形化输出 yum install toilet yum install figlet 4.aafire 小火…

Python打造的智能家居神器:Home Assistant

引言 在数字化时代&#xff0c;智能家居系统越来越多地融入我们的生活。而为了打造一个安全、可控、高效的智能家庭环境&#xff0c;一个优秀的开源智能家居控制平台至关重要。Home Assistant以Python为开发语言&#xff0c;遵循开放源代码协议&#xff0c;专注于本地控制与隐私…

别让这6个UI设计雷区毁了你的APP!

一款成功的APP不仅仅取决于其功能性&#xff0c;更取决于用户体验&#xff0c;这其中&#xff0c;UI设计又至关重要。优秀的UI设计能够为用户带来直观、愉悦的交互体验&#xff0c;甚至让用户“一见钟情”&#xff0c;从而大大提高产品吸引力。 然而&#xff0c;有很多设计师在…

OpenHarmony 资源调度之内存管理源码分析

作者&#xff1a;张守忠 1 内存管理简介 内存管理部件位于全局资源调度管控子系统中&#xff0c;基于应用的生命周期状态&#xff0c;更新进程回收优先级列表&#xff0c;通过内存回收、查杀等手段管理系统内存&#xff0c;保障内存供给。 1.1 内存管理框架 内存管理部件主要…

【Linux】编写并运行Shell脚本程序操作实例

关于Shell脚本的介绍&#xff1a; Shell脚本是一种用于自动化任务和简化常见操作的脚本语言&#xff0c;通常用于Linux和Unix环境中。Shell脚本允许用户通过编写一系列命令和逻辑语句来执行一系列任务&#xff0c;从而提高了工作效率和自动化水平。 以下是关于Shell脚本的详细…

OSCP靶场--ZenPhoto

OSCP靶场–ZenPhoto 考点(Zenphoto < 1.4.1.4 RCE CVE-2010-3904提权) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.158.41 -sV -sC -Pn --min-rate 2500 -p- Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-11 21:14 EDT Warning: 192.16…

2024 年 3 月编程语言排行榜,Python 与其他语言之间的差距从未如此之大!

TIOBE 2024 年 3 月份的编程语言排行榜已经公布&#xff0c;官方的标题是&#xff1a;Python 与其他语言之间的差距从未如此之大&#xff08;The gap between Python and the rest has never been that large&#xff09; TIOBE 指数在二月份呈现出了相对平静的态势&#xff0…

QtCreator修改项目构建目录

文章目录 QtCreator修改项目构建目录问题描述方法一方法二 QtCreator修改项目构建目录 使用QtCreator编译Qt项目时&#xff0c;如有需求修改编译过程文件&#xff08;即Makefile、.o、.exe等文件&#xff09;存放目录&#xff0c;简单在工具–>选项–>构建和运行中修改D…

NCBI 数据下载

网上介绍的那几种直接下载NCBI数据的方法大都下载速度很慢&#xff0c;但是EBI (European Bioinformatics Institute) 下载很快&#xff0c;而且它的数据库和NCBI是共享的&#xff0c;所以我们可以直接从 EBI 下载。 1 、 确定要下载的 SRA 编号&#xff1b; 2 、 EBI (https…

每日一题---OJ题: 返回倒数第 k 个节点

片头 嗨! 小伙伴们,大家好! 今天我们来一起学习这道OJ题---返回倒数第k个结点,准备好了吗? 我们开始咯! 比如: 总共有5个结点,分别为 1->2->3->4->5 , 找倒数第一个结点,也就是"5" 题目很容易理解,我们先提供第一种思路 思路一: 假设链表长度为 n ,…

Execute-Assembly(3)

绕过检测 绕过前面检测的最简单的思路就是Patch ETW。而我想的是使用BOF进行Bypass ETW 以及Assembly加载。值得庆幸得是CobaltStrike官方以及有大佬已经做了这一部分的研究。 脚本学习 在官方的文档Beacon Object Files中&#xff0c;详细描写了怎么使用CNA和BOF。根据文档提供…

【opencv】示例-detect_blob.cpp

// 导入所需的OpenCV头文件 #include <opencv2/core.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/highgui.hpp> #include <opencv2/features2d.hpp> // 导入向量和映射容器 #include <vector> #include <map> // 导入输入输出…

阿里云租用服务器GPU配置报价单_1年_一个月_1小时价格表

阿里云GPU服务器租用价格表包括包年包月价格、一个小时收费以及学生GPU服务器租用费用&#xff0c;阿里云GPU计算卡包括NVIDIA V100计算卡、T4计算卡、A10计算卡和A100计算卡&#xff0c;GPU云服务器gn6i可享受3折优惠&#xff0c;阿里云服务器网aliyunfuwuqi.com分享阿里云GPU…

智能制造六大核心发展方向,驱动企业数字化转型

在制造过程中&#xff0c;智能制造展现出非凡的活力&#xff0c;它使人与智能机器的协同工作成为可能。这不仅将制造自动化的概念提升至一个新的层次&#xff0c;更将其扩展至柔性化、智能化和高度集成化的领域。通过这样的革新&#xff0c;我们得以实现数字化智能工厂的落地生…

Vue的学习之旅-part5

Vue的学习之旅-part5 虚拟DOM的原理用JS模拟DOM结构 vue的方法、计算属性、过滤器computed:{} 计算属性computed计算属性的完全体computed计算属性和methods方法的区别&#xff1a;过滤器&#xff1a;filters:{ 多个方法 } Vuex 状态管理模式 前几篇博客: Vue的学习之旅-part1 …

城市道路井盖破损丢失目标检测数据集VOC-1377张

数据集格式&#xff1a;Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件&#xff0c;仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数)&#xff1a;1377 标注数量(xml文件个数)&#xff1a;1377 标注类别数&#xff1a;4 标注类别名称:["jg","jg…

ARM64架构栈帧回溯

文章目录 前言一、栈帧简介二、demo演示 前言 请参考&#xff1a;ARM64架构栈帧以及帧指针FP 一、栈帧简介 假设下列函数调用&#xff1a; funb() {func() }funa() {funb() }main() {funa() }main函数&#xff0c;funa函数&#xff0c;funb函数都不是叶子函数&#xff0c;其…

AWS服务器有哪些优势?

作为一家总部在美国的公司&#xff0c;AWS为什么会受到中国企业的喜爱&#xff1f;他有什么优势&#xff1f;九河云作为AWS合作伙伴&#xff0c;将会带读者展现使用AWS的优势。 首先是作为跨国企业&#xff0c;AWS在全球有数十个区域节点&#xff0c;这种广泛的地域覆盖不仅有…