【初阶数据结构】深入解析顺序表:探索底层逻辑

news2024/11/17 18:18:24

请添加图片描述

🔥引言

本篇将深入解析顺序表:探索底层逻辑,理解底层是如何实现并了解该接口实现的优缺点,以便于我们在编写程序灵活地使用该数据结构。

请添加图片描述
Alt

🌈个人主页:是店小二呀
🌈C语言笔记专栏:C语言笔记
🌈C++笔记专栏: C++笔记
🌈初阶数据结构笔记专栏: 初阶数据结构笔记

🌈喜欢的诗句:无人扶我青云志 我自踏雪至山巅
请添加图片描述

文章目录

  • 一、线性表的概念
  • 二、顺序表的概念
  • 三、顺序表的分类
  • 四、实现顺序表的相关接口(Seqlist.h)
  • 五、正式开始模拟实现顺序表
    • 5.1 顺序表的初始化
    • 5.2 顺序表的扩容(为插入数据提供保障)
    • 5.3 顺序表的插入数据
      • 5.3.1 顺序表的尾插
      • 5.3.2 顺序表的头插
    • 5.4 顺序表的删除数据
      • 5.4.1 顺序表的尾删
      • 5.4.2 顺序表的头删
    • 5.5 查找指定位置的下标
    • 5.5 顺序表的任意位置插入(pos是下标)
    • 5.6 顺序表的任意位置删除(pos是下标)
    • 5.7 顺序表的判空(主要是否存在有效元素)
    • 5.8 顺序表的打印
    • 5.9 顺序表的销毁
  • 六、顺序表的优缺点
  • 七、顺序表和链表的区别

一、线性表的概念

线性表(linear list)n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使 用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串等。线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储

二、顺序表的概念

顺序表属于线性表的其中一种。顺序表在逻辑、物理结构上是连续,顺序表底层逻辑实现一般是数组。关于物理结构上连续是指一段物理地址连续的存储单元依次存储数据元素的结构

三、顺序表的分类

顺序表分为两种:静态顺序表和动态顺序表,每一种都属于它自己的价值,在实际中。一般使用动态顺序表做的,比如我们经常用的通讯录(因为静态顺序表只适合事前知道需要多少内存的情况下,不然会出现申请多少内存问题)

在这里插入图片描述

四、实现顺序表的相关接口(Seqlist.h)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

五、正式开始模拟实现顺序表

提前说明下:每一个接口都需要断言下传过来的指针是否为空指针去判断是否是一个有效的结构体变量。如果是第一次接触数据结构,首先需要搞清楚size代表了有效元素个数,而capacity代表的是这块空间的大小或者容量,这里两个东西不是一个意思。

小技巧:在循环中如果不知道结束条件的话,带入临界值去尝试是否符合条件

5.1 顺序表的初始化

void SLInit(SL* phead)
{
	assert(phead);
	phead->a = NULL;
	phead->size = phead->capacity = 0;
}

这里需要注意的是:空间上没有硬性要求不开空间,可以适当开辟空间,当空间不足时,需向系统申请空间。

5.2 顺序表的扩容(为插入数据提供保障)

void SLChekckCapacity(SL* phead)
{
	assert(phead);
	if (phead->size == phead->capacity)
	{
		int newcapacity =phead->capacity==0?4:phead->capacity * 2;
		SLDataType* pphead = (SLDataType*)realloc(phead->a, sizeof(SLDataType) * newcapacity);
		if (pphead == NULL)
		{
			perror("realloc fail!!");
			return 1;
		}
		phead->a = pphead;
		phead->capacity = newcapacity;
	}
}

这里需要注意的是:当有效元素个数等于当前空间容量为了下一次的插入元素,需要进行扩容操作。由于扩容功能需要多次调用,对此可以考虑设计为一个接口SLChekckCapacity进行复用

在接口底层逻辑中,值得我们注意的是当capacity为空(零乘任何数为零),会导致申请空间大小出现错误。这里有两种解决措施:提前开辟一定量空间或者使用新的变量newcapacity进行接收,防止数据丢失。最好不要phead直接接收扩容的地址,防止扩容(第二种情况)失败导致找不到之前空间地址。开辟以字符类型来维修开辟的空间,需要为‘\0‘开辟一个空间。

5.3 顺序表的插入数据

插入分为三类:头插\尾插\任意位置插入(其中任意位置插入,在实现查找功能先放着)

5.3.1 顺序表的尾插

void SLPlusBack(SL*phead, SLDataType x)
{
	assert(phead);
    if(phead->size == phead->capacity)
	SLChekckCapacity(phead);
	phead->a[phead->size] = x;
	phead->size++;
}

这里需要注意的是:这里主要利用下标赋值完成插入的操作

5.3.2 顺序表的头插

void SLPlusFront(SL* phead, SLDataType x)
{
	assert(phead);
    if(phead->size == phead->capacity)
	SLChekckCapacity(phead);
	for (int i = phead->size; i >0; i--)
	{
		phead->a[i] = phead->a[i - 1];
	}
	phead->a[0] = x;
	phead->size++;
}

这里需要注意的是:原数据整体向后移动,首次位置会数据重复,将首元素将其覆盖,实现头插的效果。

设置循环条件,数据向后移动(覆盖并数值不丢失)。如果是从前先后覆盖,比如1 2 3 4 5 变成 1 1 2 3 4 5,将i的值赋值给i+1i从首元素下标开始并且覆盖方式nums[i+1]=nums[i]

5.4 顺序表的删除数据

删除分为三类:头删 尾删 任意位置删除(其中任意位置删除,在实现查找功能先放着)

提前说明:空表无法进行删除数据,需要在删除操作之前进行断言检查assert(phead->a)

5.4.1 顺序表的尾删

void SLPopBack(SL* phead)
{
	assert(phead);
	assert(phead->a);
	phead->size--;
}

这里需要注意的是:这里删除不是将数据设为0就是删除数据。正确的做法,通过size(有效数据个数)个数控制。顺序表不访问size外的无效数据,那么从某种意义上是删除了数据(班里有位同学退学,班里人数少一位,同学还是存在,只是座位没有它),不需要空间是否浪费,尾插数据时,可能下次还是用到那个空间。

5.4.2 顺序表的头删

void SLPopFront(SL* phead)
{
	assert(phead);
	assert(phead->a);
	for (int i = 0; i < phead->size-1; i++)
	{
		phead->a[i] = phead->a[i + 1];
	}
	phead->size--;
}

这里需要注意的是:数组删除数据的方式就是覆盖数据,那么只需要从后向前覆盖,首元素将被覆盖或者被删除

设置循环条件,数据向前移动(覆盖并数值不丢失)。如果是从后先前覆盖,比如1 2 3 4 5变成 2 3 4 5 5,将i+1的值赋值给ii从首元素下标开始并且覆盖方式nums[i]=nums[i+1]

5.5 查找指定位置的下标

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

这里需要注意的是:遍历顺序表,如果满足条件返回当前位置的下标,没有找到返回一个负数表示找不到。

5.5 顺序表的任意位置插入(pos是下标)

void SLInsert(SL* phead, int pos, SLDataType x)
{
	assert(phead);

	assert(0 <= pos && pos <= phead->size);
		SLChekckCapacity(phead);
		for (int i = phead->size; i>pos;i--)
		{
			phead->a[i] = phead->a[i-1];//pos+1 pos-->注意覆盖的顺序,向后就是后面开始
		}
		phead->a[pos] = x;	
		phead->size++;
}

这里需要注意的是:任意位置上的修改(任意是相对的,需要对pos进行限制)。具体流程就是以下标pos为界,pos之后的数据向后移动(跟头插类似,主要是在循环条件略显差异)

5.6 顺序表的任意位置删除(pos是下标)

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

这里需要注意的是:任意位置上的修改(任意是相对的,需要对pos进行限制)。具体流程就是以下标pos为界,pos之后的数据向前移动(跟头删是类似的,主要是在循环条件略显差异)

小总结:顺序表通过任意位置插入\删除去取代头尾的插入\删除操作,至于为什么需要了解头尾的插入\删除操作,虽然相当于基础,也是需要学习的(只有学会1+1,才能学会7+8)

5.7 顺序表的判空(主要是否存在有效元素)

bool SLEmpty(SL*phead)
{
	assert(phead);
    assert(phead->a);
    return phead->size==0;
}

5.8 顺序表的打印

void SLPrintData(SL*phead)
{
	assert(phead);
	for (int i = 0; i < phead->size; i++)
	{
		printf("%d ", phead->a[i]);
	}
	printf("\n");
}

5.9 顺序表的销毁

void SLDestory(SL*phead)
{
    assert(phead);
    if (phead->a)
    {
        free(phead->a);//free该前顺序表的动态开辟的空间
        phead->a = NULL;
        phead->size = phead->capacity = 0;
    }	
}

六、顺序表的优缺点

顺序表的优点:支持下标随机访问(时间复杂度O(1))

顺序表的缺点:

  • 在实现插入和删除操作过程中,通过大量的移动数据,效率较低
  • 空间不足需要扩容并且需要付出一定的代价,可能存在空间浪费
  • 只适合尾插尾删

七、顺序表和链表的区别

不同点顺序表链表
存储空间上物理上一定连续逻辑上连续,但物理上不一定 连续
随机访问支持O(1)不支持:O(N)
任意位置插入或者删除 元素可能需要搬移元素,效率低 O(N)只需修改指针指向
插入动态顺序表,空间不够时需要 扩容没有容量的概念
应用场景元素高效存储+频繁访问任意位置插入和删除频繁
缓存利用率

不管是哪一种数据结构都有他的优点和缺点,对此在使用数据结构中应该知道它的优缺点是什么,加以合理地利用解决实际中的问题。


请添加图片描述

以上就是本篇文章的所有内容,在此感谢大家的观看!这里是店小二初阶数据结构笔记,希望对你在学习初阶数据结构中有所帮助!

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

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

相关文章

【必会面试题】布隆过滤器

目录 基本组成部分&#xff1a;工作原理&#xff1a;特点&#xff1a;一个简单的示例应用场景&#xff1a; 布隆过滤器&#xff08;Bloom Filter&#xff09;是一种空间效率极高且查询速度很快的概率型数据结构&#xff0c;用于测试一个元素是否属于一个集合。布隆过滤器的基本…

【CGAL】Region_Growing检测圆柱,保存结果并输出圆柱体参数

目录 说明代码展示结果展示问题说明 说明 这篇博客以代码为主&#xff0c;使用CGAL中的region growing方法检测圆柱体。将不同的圆柱按不同颜色保存&#xff0c;并输出圆柱体的中心坐标、轴方向以及半径。 region growing的具体思想网上的文章已经有很多&#xff0c;可以参考这…

万界星空科技定制化MES系统,实现数字化生产

一、MES生产管理系统强调三个方面&#xff1a; 1、MES是对整个车间制造过程的优化&#xff0c;而不是单一的解决某个生产瓶颈。 2、MES必须提供实时收集生产过程中数据的功能&#xff0c;并作出相应的分析和处理。 3、MES需要与计划层和控制层进行信息交互&#xff0c;通过企业…

算法day25

第一题 394. 字符串解码 解法&#xff1a;模拟栈的完成上述的操作&#xff1b; 分析&#xff1a; 下面以如图的字符串来分析&#xff1b; 首先定义一个数字栈用来存放数字&#xff0c;同时定义一个容器stringbuffer栈&#xff0c;里面用来存放字符串&#xff1b; 1、遇到数字&…

若依RuoYi-Vue分离版—配置多数据源

若依RuoYi-Vue分离版—配置多数据源 一、修改application-druid.yml二、修改pom文件&#xff0c;引入依赖第一种&#xff1a;下载jar包到本地&#xff0c;然后引入&#xff08;我这边用的是这种&#xff09;本地引入的&#xff0c;打包时需要加上配置 第二种&#xff1a;从远程…

JAVA开发 使用Apache PDFBox库生成PDF文件,绘制表格

1. 表格位置定点 2.执行效果展示&#xff08;截取PDF文件图片&#xff09; 3.执行代码 当我们使用Apache PDFBox库在PDF文件中创建带有表格的内容&#xff0c;需要遵循几个步骤。PDFBox本身并没有直接的API来创建表格&#xff0c;但我们可以通过定位文本、绘制线条和单元格矩形…

如何在Visual Studio Code中禁用Less文件保存时自动编译为CSS的功能

第一步&#xff1a;点击扩展&#xff0c;搜索Easy Less&#xff0c;并找到对应的扩展设置 第二步&#xff1a;点击在setting.json中编辑 第三步&#xff1a;将此段代码复制粘贴 "compress": false, // 是否压缩"sourceMap": false, // 是否生成map文件&am…

揭秘ASA归因统计的奥秘,Xinstall带您轻松上手!

在移动互联网时代&#xff0c;App推广已成为企业获取用户、提升品牌知名度的重要手段。然而&#xff0c;如何准确衡量推广效果&#xff0c;如何精准定位目标用户&#xff0c;一直是困扰着众多App运营者的难题。今天&#xff0c;我们就来谈谈ASA&#xff08;Apple Search Ads&am…

怎么监控电脑屏幕上的画面?监控电脑屏幕的优秀软件有哪些

怎么监控电脑屏幕上的画面呢&#xff1f;当然是用监控软件啦&#xff0c;它的功能超乎你的想象&#xff0c;下面我将详细介绍如何使用监控软件来监控屏幕&#xff0c;内容将包含监控软件的选择、安装、配置以及具体监控功能的实现等方面。 一、选择监控软件 在选择监控软件时&…

SonarQube安全扫描常见问题

目录 一、SonarQube质量报告 二、SonarQube扫描常见问题和修复方法 三、SonarQube质量配置 最近小编在使用SonarQube工具进行代码扫描&#xff0c;检查代码异味&#xff0c;系统漏洞等&#xff0c;实际过程中也遇到了不少问题&#xff0c;这篇文章主要列举我遇到的常见问题和…

鸿蒙开发文件管理:【@ohos.document (文件交互)】

文件交互 说明&#xff1a; 本模块首批接口从API version 6开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。本模块接口后续将废弃。不建议在OpenHarmony使用以下接口&#xff0c;调用以下接口将抛出异常。 导入模块 import document from ohos.d…

H1B签证/年薪近$6.5万|美国加州大学戴维斯分校博士后申请成功

N博士信息与通信工程专业毕业,希望到美国加州及周边地区从事博士后工作&#xff0c;且最好是H1B签证。我们为其申请到美国加州大学洛杉矶分校及戴维斯分校的职位&#xff0c;年薪为64,480美元&#xff0c;最终其选择可以办理H1B签证的加州大学戴维斯分校。 N博士背景&#xff1…

Django中配置日志

在Django中配置日志的方法非常简单&#xff0c;只需要在 setting 文件中添加配置项&#xff0c;系统会自动生成相应的日志文件&#xff0c;也可以配置调试时显示内容&#xff0c;报错发送邮件等操作。 在setting.py中添加以下配置。 # 日志配置 LOGS_DIRS os.path.join(BASE…

解决群晖NAS无法拉取docker镜像问题

一、问题描述 由于国内的docker已经被管控&#xff0c;直接在群晖NAS的docker面板上是无法直接查询到需要的docker镜像内容&#xff0c;我们需要通过SSH连接到群晖使用docker命令进行拉取镜像使用&#xff0c;如下图所示&#xff1a; 注意&#xff1a;若要通过SSH连接群晖NAS则…

【python中的转义字符】

在Python中&#xff0c;除了换行符&#xff08;\n&#xff09;和制表符&#xff08;\t&#xff09;&#xff0c;还有许多其他的转义字符和字符串格式化符号可以使用。以下是一些常见的例子&#xff1a; 1、常见的转义字符 ### 常见的转义字符 1. **换行符**: \n 2. **制表符*…

Odoo实现自动拉取gitee代码,自动升级模块

系统通过计划任务每天从指定的git仓库获取仓库tag,并存储在数据库中 系统管理员(base.group_system)每次刷新页面,在后台判断最新的tag是否已安装或已忽略来提醒是否有新的版本。 一、依赖 模块依赖python第三方包GitPython,安装方法: pip install GitPython GitP…

Camtasia Studio2024破解神器下载,轻松上手视频剪辑

嘿&#xff01;今天我要和大家分享一个神奇的软件——Camtasia Studio2024最新版的破解安装包&#xff01;&#x1f3ac; 作为一个视频制作爱好者&#xff0c;我一直在寻找一款功能强大、易于操作的视频编辑软件。而Camtasia Studio2024就是我心目中的完美选择&#xff01;它不…

二刷算法训练营Day28 | 回溯算法(4/6)

目录 详细布置&#xff1a; 1. 93. 复原 IP 地址 2. 78. 子集 3. 90. 子集 II 详细布置&#xff1a; 1. 93. 复原 IP 地址 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔…

网络协议四

一、云中网络 物理机的劣势&#xff1a; 1&#xff09;一旦需要扩容 CPU、内存、硬盘&#xff0c;都需要去机房手动弄&#xff0c;非常麻烦 2&#xff09;采购的机器往往动不动几百 G 的内存&#xff0c;而每个应用往往可能只需要 4 核 8G 3&#xff09;一台机器&#xff0c;…

pnpm : 无法加载文件 C:\Users\xxxxx\AppData\Roaming\npm\pnpm.ps1,因为在此系统上禁止运行脚本。

vscode中执行pnpm install的时候&#xff0c;直接报了上面的错误。 解决&#xff1a; 然后输入&#xff1a;set-ExecutionPolicy RemoteSigned&#xff0c;按回车&#xff0c;然后根据提示&#xff0c;我们选A。 然后回车。 这样我们再次回到vscode中的我们就会发现可以了。 …