成为编程大佬!!----->数据结构与算法(2)——顺序表!!

news2024/9/26 1:29:08

前言:线性表是数据结构与算法的重中之重所有具有线性逻辑结构的数据结构,都能称为线性表。这篇文章我们先来讨论线性表中的顺序表,顺序表和线性表都是后续实现栈,树,串和图等等结构的重要基础。

目录

❀简单介绍线性表

❀顺序表

❀顺序表的存储

❀动态存储

❀静态存储

❀静态存储与动态存储的优缺点

❀顺序表操作

❀1.初始化顺序表

❀2.销毁顺序表

❀3.插入数据

❀插入数据之判断已满否

❀插入操作之尾插

❀插入操作之头插

❀插入数据之插入指定位置

❀4.删除数据

❀删除数据之尾删

❀删除数据之头删

❀删除数据之删除指定位置

❀5.查找顺序表单个数据

❀⭐6.打印顺序表中所有数据

❀结语


简单介绍线性表

对于某种数据结构的存储特点可以从两个方面来看:逻辑结构物理结构

逻辑结构由人想像出来的抽象结构

物理结构在内存上的存储结构

下面要介绍的顺序表——逻辑结构上,是一段依次排列的、连续存储的数据;在物理结构上,也是连续存储在内存上的。也就是说,顺序表在逻辑结构和物理结构上都是线性的而只要在逻辑结构上是线性的,它就是线性表)。

顺序表

因为顺序表在物理结构上是连续存储的,所以顺序表的本质就是数组。但是数据结构与算法需要对数据进行相关的管理(如增删查改),因此,我们需要对存储数据的数组进行封装。

顺序表的存储

我们用结构体来封装顺序表,结构体内除了包括存储数据的数组之外,我们再定义两个成员,用来保存顺序表的最大存储容量(capacity)顺序表的实际存储的有效数据(size)

动态存储

//顺序表中数据类型
typedef int SLdatatype;
//顺序表存储结构
typedef struct SeqList
{
	SLdatatype* arr;
	int capacity;
	int size;
}SL;

i.动态存储需要申请动态数组,通过调用动态内存管理函数来申请空间,然后通过指针arr保存申请空间的地址来形成动态数组。

ii.动态存储的顺序表,使用的是堆上的空间

静态存储

#define M 100

//顺序表中数据类型
typedef int SLdatatype;
//顺序表存储结构
typedef struct SeqList{
    SLdatatype arr[M];
    int capacity;
    int size;
}SL;

i.静态存储,只需直接创建数组即可。数组大小是定死的。

ii.静态存储的顺序表,使用的是栈上的空间

静态存储与动态存储的优缺点

然而在实际编码项目中,出现过量的空间浪费或者空间不足都有可能导致严重的问题。空间浪费会消耗不必要的存储成本; 空间不足,会导致数据的泄露或者丢失。这些情况都会对管理者和用户造成严重损失。

因此,我们优先使用申请空间自由度高的动态存储来实现顺序表(以下操作均以动态存储为基础来实现)。

顺序表操作

下方非重点操作打了星星。

1.初始化顺序表

//初始化
void SLInit(SL* ps)
{
	//全部置空置零
	ps->arr = NULL;
	ps->capacity = 0;
	ps->size = 0;
}

将顺序表的成员全部置空置零。

2.销毁顺序表

//销毁顺序表
void SLDestroy(SL* ps)
{
	if (!ps)
	{
		printf("empty ptr!\n");
		return;
	}
	free(ps->arr);//释放动态数组
	SLInit(ps);//初始化顺序表
}

i.首先要判断传入的顺序表指针是否为空。一来可以保证程序合理合法运行,二来也可以消除VS的警告(ps可能为空指针)

ii.释放动态数组

iii.初始化顺序表

3.插入数据

插入新的数据就会占用顺序表容量,因此我们要确保顺序表有充足的容量如果不够,我们得进行扩容

插入数据之判断已满否
void SLCheckSpace(SL* ps)
{
    if (!ps)
    {
        printf("empty ptr\n");
        return;
    }
    if (ps->capacity == ps->size)//空间已满
    {
        int newCapacity = 1;
        if (ps->capacity)
        {
            newCapacity = ps->capacity;
        }
        int* temp = (int*)realloc(ps->arr, sizeof(SLdatatype) * 2 * newCapacity);//扩容
        if (temp)//扩容成功
        {
            ps->arr = temp;//接收扩容后地址
            ps->capacity = 2 * newCapacity;//修改顺序表容量
        }
    }
    return;
}

i.首先要判断传入的顺序表指针是否为空一来可以保证程序合理合法运行,二来也可以消除VS的警告(ps可能为空指针)

ii.如果空间已满,我们就进行扩容。扩容方式将容量扩大到原来的两倍

iii.修改顺序表扩容后的容量ps->capcity。

!!注意!!如果顺序表刚进行初始化操作容量是零,此时容量乘2之后还是零

因此,我们要设置默认值newcapacity为1。当容量为0的时候,使newcapacity不变;当容量不为零时,使newcapacity等于原容量.

PS:为什么是要扩大到原来的两倍呢?

因为,如果我们在容量不够的时候,只扩容多一个数据单位的容量,那么在下次插入时,又要进行一次扩容。虽然没有空间浪费,但是次数繁多的扩容操作,会让程序的时间效率大大的降低。所以,我们采用这种扩容方式,这样就能大大减少扩容的次数(因为每次都使得顺序表的容量呈指数级增长),同时这样的操作所产生的浪费也是可以控制的。

再补充一点,我们也可以让顺序表的容量每次扩大到原来的3倍,4倍,5倍都可以,按照实际情况来选择即可。

插入操作之尾插
//尾插
void SLPushBack(SL* ps, SLdatatype x)
{
	if (!ps)//检查顺序表指针
	{
		printf("empty ptr!\n");
		return;
	}
	SLCheckSpace(ps);//检查扩容
	ps->arr[ps->size++] = x;//尾插后,size++
	return;
}

i.首先要判断传入的顺序表指针是否为空。一来可以保证程序合理合法运行,二来也可以消除VS的警告(ps可能为空指针)。

ii.进行检查扩容

iii.直接在顺序表最后的位置插入新数据(索引为ps->size)。

iiii.顺序表有效数据数ps->size++

插入操作之头插
//头插
void SLPushFront(SL* ps, SLdatatype x)
{
    if (!ps)
    {
        printf("empty ptr!\n");
        return;
    }
    SLCheckSpace(ps);
    int i = ps->size;
    while (i >= 1)
    {
        ps->arr[i] = ps->arr[i - 1];
        i--;
    }
    ps->arr[0] = x;
    ps->size++;
    return;
}

i.首先要判断传入的顺序表指针是否为空。一来可以保证程序合理合法运行,二来也可以消除VS的警告(ps可能为空指针)。

ii.检查扩容

iii.将所有的数据往后挪一个数据单位。从后面的数据开始依次往后挪,否则较后面的数据会被覆盖导致丢失。

iiii.将新数据插入顺序表第一个位置

iiiii.顺序表有效数据ps->size++

插入数据之插入指定位置
//插入指定位置数据
void SeqListInsert(SL* ps, SLdatatype x, int pos)
{
	if (!ps)
	{
		printf("empty ptr!\n");
		return;
	}
	if (pos < 0 || pos >= ps->size)
	{
		printf("wrong pos!\n");
		return;
	}
	SLCheckSpace(ps);
	for (int i = ps->size; i > pos; i--)//pos后数据往后挪1位
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[pos] = x;//插入数据
	ps->size++;//size加一
	return 0;
}

i.首先要判断传入的顺序表指针是否为空。一来可以保证程序合理合法运行,二来也可以消除VS的警告(ps可能为空指针)。

ii.判断插入位置pos是否合法

iii.检查扩容

iiii.将pos往后的数据都向后挪动一个数据单位。要从后面的数据开始依次往后挪,否则较后面的数据会被覆盖导致丢失。

iiiii.插入新数据到pos位置

iiiiii.顺序表有效数据容量ps->size++

4.删除数据

删除数据之尾删
//尾删
void SLPopBack(SL* ps, SLdatatype* x)
{
	if (!ps)
	{
		printf("empty ptr!\n");
		return;
	}
	if (ps->size == 0)
	{
		printf("无数据可删!\n");
		return;
	}
	*x = ps->arr[--ps->size];//x接收删除的数据
	//最终,size会被减1,删除的数据虽然仍保存在数组中,但不影响后续操作。
	return;
}

i.首先要判断传入的顺序表指针是否为空。一来可以保证程序合理合法运行,二来也可以消除VS的警告(ps可能为空指针)。

ii.判断顺序表是否还有数据可删除

iii.用x接收删除的数据

iiii.顺序表有效数据ps->size--

!!注意!!虽然顺序表中,实际上还存储着删除了的数据,但是这个数据由于ps->size的减小,已经无法访问或者使用,并且该残留数据也不会影响后续的操作。

删除数据之头删
//头删
void SLPopFront(SL* ps, SLdatatype* x)
{
	if (!ps)
	{
		printf("empty ptr!\n");
		return;
	}
	if (ps->size == 0)
	{
		printf("无数据可删!\n");
		return;
	}
	*x = ps->arr[0];//接收删除的数据
	int i = 1;
	while (i < ps->size)//数据整体往前挪
	{
		ps->arr[i - 1] = ps->arr[i];
		i++;
	}
	ps->size--;//size减1
	return;
}

i.首先要判断传入的顺序表指针是否为空。一来可以保证程序合理合法运行,二来也可以消除VS的警告(ps可能为空指针)。

ii.判断顺序表是否还有数据可删除

iii.用x接收删除的数据

iiii.将第一位往后的所有数据都往前挪一位,从而覆盖第一位数据。要从前面的数据开始依次往前挪,否则较前面的数据会被覆盖导致丢失。

iiii.顺序表有效数据数ps->size--

!!注意!!虽然顺序表经过该操作之后,ps->arr[size]上还保存着数据,但是这个数据由于ps->size的减小,已经无法访问或者使用,并且该残留数据也不会影响后续的操作。

删除数据之删除指定位置
//删除指定位置数据
void SeqListErase(SL* ps, int pos)
{
	if (!ps)
	{
		printf("empty ptr!\n");
		return;
	}
	if (pos < 0 || pos >= ps->size)
	{
		printf("wrong pos!\n");
		return;
	}
	if (ps->size == 0)
	{
		printf("无数据可删!\n");
		return;
	}
	for (int i = pos + 1; i < ps->size; i++)
	{
		ps->arr[i - 1] = ps->arr[i];
	}
	ps->size--;
	return;
}

i.首先要判断传入的顺序表指针是否为空。一来可以保证程序合理合法运行,二来也可以消除VS的警告(ps可能为空指针)。

ii.判断插入位置pos是否合法

iii.判断顺序表是否还有数据可删除

iiii.将pos往后的数据都向前挪动一个数据单位要从前面的数据开始依次往前挪,否则较前面的数据会被覆盖导致丢失。

iiiii.顺序表有效数据ps->size--

5.查找顺序表单个数据

//查找顺序表单个数据
int SeqListFind(SL* ps, SLdatatype x)
{
	if (!ps)
	{
		printf("empty ptr!\n");
		return -1;
	}
	if (ps->size == 0)
	{
		printf("顺序表为空!\n");
		return -1;
	}
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->arr[i] == x)
		{
			printf("数据x在顺序表的 %d 索引处\n", i);
			return i;
		}
	}
	printf("不存在这样的数据x\n");
	return -1;
}

i.首先要判断传入的顺序表指针是否为空。一来可以保证程序合理合法运行,二来也可以消除VS的警告(ps可能为空指针)。

ii.判断顺序表是否有数据。没有数据就没必要查找了。

iii.循环遍历顺序表来查找。找到了就返回其索引;没找到就打印数据不存在的信息,返回-1。

⭐6.打印顺序表中所有数据

(实际打印方式不只下方代码一种,可根据实际情况设计打印操作)

//输出顺序表数据
void SLPrint(SL* ps)
{
	if (!ps)
	{
		printf("empty ptr!\n");
		return;
	}
	if (ps->size == 0)
	{
		printf("顺序表为空!\n");
		return;
	}
	printf("当前顺序表数据为:");
	for (int i = 0; i < ps->size; ++i)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n");
	return;
}

i.首先要判断传入的顺序表指针是否为空。一来可以保证程序合理合法运行,二来也可以消除VS的警告(ps可能为空指针)。

ii.判断顺序表是否有数据。没有数据就没必要打印了。

iii.循环遍历顺序表来打印

结语

看完这篇博客,相信你已经对算法复杂度有了深刻认识了。有什么疑问和困惑欢迎来评论区留言!!🤩我一定尽力及时解答!!制作不易,求关注!!求点赞!!之后还会有更多有用的干货博客会发出哦!!欢迎做客我的主页!!❤❤Elnaij-CSDN博客❤❤

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

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

相关文章

YOLOv10改进 | 主干/Backbone篇 | 轻量级网络ShuffleNetV1(附代码+修改教程)

一、本文内容 本文给大家带来的改进内容是ShuffleNetV1&#xff0c;这是一种为移动设备设计的高效CNN架构。它通过使用点群卷积和通道混洗等操作&#xff0c;减少了计算成本&#xff0c;同时保持了准确性&#xff0c;通过这些技术&#xff0c;ShuffleNet在降低计算复杂度的同时…

yolov8、RTDETR无法使用多个GPU训练

yolov8、RTDETR无法使用多个GPU训练 网上看了好多解决方法&#xff1a; 什么命令行 CUDA_VISIBLE_DEVICES0,1 python train.py 环境变量都不行 最后找到解决方案&#xff1a;在ultralytics/engine/trainer.py 中的第246行 将 self.model DDP(self.model, device_ids[RANK])…

Web 应用程序开发的前沿:2024 年会发生什么??

Web 应用程序开发是发展最快的领域之一&#xff0c;令人印象深刻地改变了网络空间的给定面貌。 随着我们进入 2024 年&#xff0c;许多进步趋势和技术正在出现&#xff0c;它们整合了开发人员和商人探索他们才能的新领域。 这篇博客将介绍有关创建 Web 应用程序的最新趋势的想法…

记一次若依框架和Springboot常见报错的实战漏洞挖掘

目录 前言 本次测实战利用图​ 1.判段系统框架 2.登录页面功能点测试 2.1 弱口令 2.2 webpack泄露信息判断 2.3 未授权接口信息发现 3.进一步测试发现新的若依测试点 3.1 默认弱口令 3.2 历史漏洞 4.访问8080端口发现spring经典爆粗 4.1 druid弱口令 4.2 SwaggerU…

牛顿力学和拉格朗日力学求解atwood machine问题对比

一个半径为 R R R、转动惯量为 I I I 的圆盘。绳子与圆盘无滑动&#xff0c;质量 m 2 m_2 m2​ 的物体在重力 g g g 作用下下坠&#xff0c;带动质量 m 1 m_1 m1​ 的物体上升。求 m 1 m_1 m1​和 m 2 m_2 m2​ 的加速度 a a a。 牛顿力学方法 对质量 m 1 m_1 m1​ 和 …

攻防世界(PHP过滤器过滤)file_include

转换过滤器官方文档&#xff1a;https://www.php.net/manual/zh/filters.convert.php#filters.convert.iconv 这道题因为convert.base64-encode被过滤掉了&#xff0c;所以使用convert.iconv.*过滤器 在激活 iconv 的前提下可以使用 convert.iconv.* 压缩过滤器&#xff0c; 等…

Jmeter多用户登录操作实战

在使用Jmeter性能测试时,首先要解决的问题恐怕就会并发压测和多用登录的问题.今天就一篇文章讲清楚这两个问题的解决方案: 一.多并发压测如何配置线程? &#xff08;1&#xff09;同时并发&#xff1a;设置线程组、执行时间、循环次数&#xff0c;这种方式可以控制接口请求的…

Axure-黑马

Axure-黑马 编辑时间2024/7/12 来源&#xff1a;B站黑马程序员 需求其他根据&#xff1a;visio&#xff0c;墨刀 Axure介绍 Axure RP是美国Axure Software Solution给公司出品的一款快速原型大的软件&#xff0c;一般来说使用者会称他为Axure 应用场景 拉投资使用 给项目团…

(自用)高并发实现高效内存管理

高并发下传统方式的弊端 C语言常用的内存操作函数 C下采用new进行内存分配&#xff0c;delete进行内存释放。 弊端一 分配内存需要进入内核态&#xff0c;总分配大小不变的情况下&#xff0c;多次分配较小的内存导致了变态频繁&#xff0c;降低系统效率. 弊端二 弊端三 情形…

LayoutLMv2:视觉丰富文档理解的多模态预训练

文本和布局的预训练由于其有效的模型架构和大规模未标记扫描/数字出生文档的优势&#xff0c;在各种视觉丰富的文档理解任务中被证明是有效的。我们提出了具有新的预训练任务的LayoutLMv2架构&#xff0c;以在单个多模态框架中对文本、布局和图像之间的交互进行建模。具体而言&…

JVM:SpringBoot TomcatEmbeddedWebappClassLoader

文章目录 一、介绍二、SpringBoot中TomcatEmbeddedWebappClassLoader与LaunchedURLClassLoader的关系 一、介绍 TomcatEmbeddedWebappClassLoader 是 Spring Boot 在其内嵌 Tomcat 容器中使用的一个类加载器&#xff08;ClassLoader&#xff09;。在 Spring Boot 应用中&#…

【漏洞复现】方正全媒体采编系统——binary.do——SQL注入

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 方正全媒体采编系统&#xff08;FZMediaEditor&#xff09;是一…

华为交换机如何恢复出厂设置

华为交换机如何恢复出厂设置 用consol线连接交换机的consol口和笔记本相连打开securt-CRT软件&#xff0c;CRT软件设置如下图&#xff1a; 3.reset save然后输入Y 4.重启交换机 重启等待两分钟左右

数据结构:链表相关题目

链表反转 LeetCode地址&#xff1a;LCR 024. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 头插法&#xff1a; class Solution {public ListNode reverseList(ListNode head) {ListNode h1 new ListNode(-1);while(head!null){ListNode index new ListNode(head.val…

同享TXEHR V15人力管理平台DownloadFile接口任意文件下载漏洞复现 [附POC]

文章目录 同享TXEHR V15人力管理平台DownloadFile接口任意文件下载漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现同享TXEHR V15人力管理平台DownloadFile接口任意文件下载漏洞复现 [附POC] 0x01 前言 免责声…

批量制作word表格

问题背景 将excel表中的成绩内容制作为成绩单&#xff0c;每页对应一个学员的成绩&#xff0c;方便打印 代码实现 ## 导入包 import pandas as pd from docx import Document from docx.enum.text import WD_ALIGN_PARAGRAPH,WD_LINE_SPACING# 读取 Excel 内容 df pd.read_e…

FastAPI 学习之路(四十四)WebSockets

我们之前的分析都是基于http的请求&#xff0c;那么如果是websockets可以支持吗&#xff0c;答案是可以的&#xff0c;我们来看下是如何实现的。 from fastapi import WebSocket, FastAPI from fastapi.responses import HTMLResponseapp FastAPI()html """&…

mindspore打卡23天之基于MobileNetv2的垃圾分类函数式自动微分

基于MobileNetv2的垃圾分类 本文档主要介绍垃圾分类代码开发的方法。通过读取本地图像数据作为输入&#xff0c;对图像中的垃圾物体进行检测&#xff0c;并且将检测结果图片保存到文件中。 1、实验目的 了解熟悉垃圾分类应用代码的编写&#xff08;Python语言&#xff09;&a…

第11章 规划过程组(三)(11.11规划成本管理)

第11章 规划过程组&#xff08;三&#xff09;11.11规划成本管理&#xff0c;在第三版教材第403~404页&#xff1b; 文字图片音频方式 第一个知识点&#xff1a;成本管理概述 1、成本的类型&#xff08;重要知识点&#xff09; 直接成本 如项目团队差旅费、工资、项目使用的…

动态规划算法专题四--子数组系列问题

目录 题十八 最大子数组和 1、算法解析 1、确定状态&#xff1a; 2、状态转移方程&#xff1a; 3、初始化&#xff1a; 4、填表顺序&#xff1a; 5、返回值&#xff1a; 2、代码 题十九 环形子数组的最大和 1、算法解析 1、确定状态&#xff1a; 2、状态转移方程&…