【王道数据结构笔记】顺序表的动态分配代码分析

在这里插入图片描述

🎈个人主页:豌豆射手^
🎉欢迎 👍点赞✍评论⭐收藏
🤗收录专栏:数据结构
🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步!

【王道数据结构笔记】顺序表的动态分配代码分析

  • 引言
  • 一 代码
  • 二代码分析
    • 步骤1:
    • 步骤2:
    • 步骤3:
    • 步骤4:
    • 步骤5:
    • 步骤6:
    • 步骤7:
  • 总结

引言

一 代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<stdlib.h>
#define InitSize  10
typedef struct {
	int *data;
	int MaxSize;
	int length;

}SeqList;

void InitList(SeqList& L) 

{
	L.data = (int*)malloc( InitSize * sizeof(int));
	L.length = 0;
	L.MaxSize = InitSize;

}

void IncreaseSize(SeqList& L, int len)
{
	int* p = L.data;
	L.data = (int*)malloc((L.MaxSize + len) * sizeof(int));
	for (int i = 0; i < L.length; i++) 
	{
		L.data[i] = p[i];
	}
	L.MaxSize = L.MaxSize + len;
	free(p);
}



int main()

{
	SeqList L;
	InitList(L);
	IncreaseSize(L, 5);
}

二代码分析

下面是拆分后的代码,以及对每一步骤的分析:

步骤1:

#define _CRT_SECURE_NO_WARNINGS

分析:
定义了一个宏_CRT_SECURE_NO_WARNINGS,用于消除某些编译器关于安全性的警告,例如在使用malloc等函数时可能出现的警告。

步骤2:

#include <stdio.h>
#include <stdlib.h>

分析:
包含了标准输入输出库stdio.h和标准库stdlib.h,前者用于输入输出操作,后者提供了内存分配函数如mallocfree

步骤3:

#define InitSize  10

分析:
定义了一个宏InitSize,值为10,用于初始化顺序表(SeqList)的初始大小。

步骤4:

typedef struct {
    int *data;
    int MaxSize;
    int length;
} SeqList;

分析:
定义了一个结构体类型SeqList,包含一个整型指针data用于存储数据,整型MaxSize用于存储顺序表的最大容量,整型length用于存储顺序表当前的长度。

指针data

在结构体类型SeqList中,整型指针data用于存储顺序表中实际数据的内存地址。具体来说,data是一个指向整型数据的指针,它指向一个动态分配的内存区域,该区域用于存储顺序表中的元素

在顺序表中,我们通常不知道事先需要存储多少个元素,或者元素的数量可能会在运行过程中变化。因此,使用动态内存分配(如malloc)来分配存储空间是一个灵活且有效的方法。data指针就是用来管理这块动态分配的内存的。

当创建或初始化一个SeqList对象时,我们通常会为data指针分配一块足够大的内存空间来存储初始的元素。随着顺序表中元素的增加或减少,我们可能需要重新分配data指针所指向的内存空间,以适应新的存储需求。这时,我们会使用realloc或再次调用malloc来重新分配内存,并更新data指针的指向。

通过data指针,我们可以方便地访问和修改顺序表中的元素。例如,通过计算元素的索引和data指针的偏移量,我们可以直接定位到某个元素的内存位置,并进行读取或写入操作。

总之,data指针在SeqList结构体中起到了桥梁的作用,它连接了顺序表的逻辑结构和实际存储数据的内存空间。

整型Maxsize:

SeqList结构体中,整型MaxSize用于表示顺序表当前分配的最大容量。这个值通常用于在动态内存管理中跟踪已经为顺序表分配了多少内存空间

具体来说,MaxSize的作用体现在以下几个方面:

  1. 内存分配参考:当需要增加顺序表的容量时(例如,通过调用IncreaseSize函数),MaxSize会被用来计算需要分配多少额外的内存空间。这样,程序可以确保在扩展顺序表时分配足够的内存。

  2. 防止越界访问:在添加新元素到顺序表之前,通常会检查顺序表的当前长度是否已经达到MaxSize。如果达到或超过MaxSize,那么程序会知道需要增加顺序表的容量,以避免越界访问内存,这是一种常见的内存安全错误。

  3. 优化内存使用:通过跟踪MaxSize,程序可以更有效地管理内存。例如,如果顺序表的大小经常变化,但变化不大,那么可以通过适当地调整MaxSize来减少频繁的内存分配和释放操作,从而提高性能。

  4. 容量监控MaxSize也可以用于监控顺序表的内存使用情况。通过比较MaxSize和顺序表的当前长度,程序可以了解顺序表是否接近满载,从而决定是否需要进行容量调整。

优化内存具体来说是在实际应用中,如果顺序表(例如一个动态数组)的大小经常会在一个较小的范围内变动,那么频繁地进行内存分配和释放操作可能会成为性能瓶颈。

为了优化性能,我们可以采取一种策略,即不是每次顺序表大小稍有变化就立即重新分配内存,而是预留一些额外的空间,即适当增加MaxSize的值。

具体来说,当顺序表需要增加元素时,我们并不立即按照新的大小重新分配内存,而是检查当前预留的空间是否足够。如果足够,我们就不会进行内存分配操作,而是直接在预留的空间中添加新元素。

只有当预留的空间不足时,我们才会进行一次较大的内存分配操作,以满足未来一段时间内可能的增长需求。

这种策略可以减少内存分配和释放的次数,因为内存分配和释放通常涉及系统调用和可能的内存碎片问题,这些操作相对耗时。

通过适当调整MaxSize的值,我们可以在一定程度上平滑这些操作对性能的影响,从而提高程序的执行效率。

需要注意的是,预留过多的空间也会浪费内存资源,因此需要在性能和内存使用之间找到一个平衡。这通常需要根据具体的应用场景和需求来决定。

总的来说,MaxSizeSeqList结构体中是一个重要的元数据成员,它帮助程序更好地管理顺序表的内存使用,确保内存安全,并优化性能。

整型length:

在顺序表(如SeqList)的数据结构中,整型length通常用于表示顺序表当前实际存储的元素个数,也就是顺序表的当前长度。这个值对于顺序表的操作和管理至关重要,具体体现在以下几个方面:

  1. 元素访问:通过length,我们可以快速知道顺序表中当前有多少个元素,从而安全地访问这些元素。例如,当我们要读取或修改顺序表中的某个元素时,需要确保该元素的索引在有效范围内(即小于length)。

  2. 添加和删除元素:当向顺序表中添加元素时,我们需要更新length以反映新添加的元素。同样地,当从顺序表中删除元素时,也需要减少length的值。通过length,我们可以方便地追踪顺序表的当前状态。

  3. 容量与长度比较lengthMaxSize的比较是顺序表管理中常见的操作。通过比较这两个值,我们可以判断顺序表是否已满(即length是否等于MaxSize),从而决定是否需要进行扩容操作。

  4. 空间效率监控length也用于监控顺序表的空间使用情况。例如,如果length远小于MaxSize,这可能意味着顺序表分配了过多的内存,存在空间浪费的情况。根据应用的需求,可以考虑是否需要进行内存收缩操作。

总之,整型length在顺序表的数据结构中扮演了记录当前元素数量、辅助元素访问和修改、管理内存空间等重要角色。它是顺序表实现中不可或缺的一部分。

步骤5:

void InitList(SeqList& L) {
    L.data = (int*)malloc(InitSize * sizeof(int));
    L.length = 0;
    L.MaxSize = InitSize;
}

分析:

定义了初始化顺序表的函数InitList,它接受一个SeqList类型的引用L作为参数。函数内部使用mallocL.data分配了InitSize个整数的空间,最后将L.lengthL.MaxSize分别初始化为0和InitSize

L.data = (int*)malloc(InitSize * sizeof(int));这行代码是C语言中用于动态内存分配的一行关键代码,它用于为一个顺序表(在这里是SeqList类型的对象L)分配初始的内存空间。具体地,这一行代码做了以下几件事:

  1. malloc(InitSize * sizeof(int))

    • malloc 是一个标准库函数,用于在堆上动态分配指定字节大小的内存。
    • InitSize 是一个变量(或常量),表示要分配的整型元素(int)的数量。
    • sizeof(int) 是一个运算符,返回int类型在特定系统或编译器上所占用的字节数。
    • InitSize * sizeof(int) 计算了总共需要分配的字节数。
  2. (int*)

    • 这是一个类型转换(或称为强制类型转换)。malloc 函数返回的是一个指向void的指针(void*),因为malloc可以分配任何类型的内存。但是,在C语言中,我们不能直接将void*类型的指针赋给其他类型的指针。因此,这里使用(int*)void*类型的指针转换为int*类型的指针。这样,我们就可以将这个指针赋值给指向整型的指针变量。
  3. L.data = ...

    • L 是一个SeqList类型的对象。
    • L.dataSeqList结构体中的一个成员,它是一个指向整型的指针,用于存储顺序表数据的实际内存地址。
    • 这一行代码将malloc返回的指针(即新分配的内存地址)赋值给L.data,这样L.data指向了新分配的内存区域

综上所述,这一行代码的目的是为顺序表L分配一个可以存储InitSize个整数的内存区域,并将这块内存的地址赋值给L.data。此后,顺序表L就可以通过L.data指针来访问和操作这些内存中的元素了。

需要注意的是,在使用malloc分配内存后,应始终检查返回值是否为NULL,以确保内存分配成功。此外,当不再需要这块内存时,应使用free函数来释放它,以防止内存泄漏。

步骤6:

void IncreaseSize(SeqList& L, int len) {
    int* p = L.data;
    L.data = (int*)malloc((L.MaxSize + len) * sizeof(int));

分析:

定义了增加顺序表大小的函数IncreaseSize,它接受一个SeqList类型的引用L和一个整数len作为参数。首先,它保存了L.data的当前地址到指针p中,以便稍后释放这块内存。然后,它使用mallocL.data重新分配了一块更大的内存空间,新的大小是原来的L.MaxSize加上增加的len个整数的大小。

步骤7:

    for (int i = 0; i < L.length; i++) {
        L.data[i] = p[i];
    }

分析:
使用循环遍历原顺序表L的每一个元素,并将这些元素复制到新分配的内存空间中。

步骤8:

    L.MaxSize = L.MaxSize + len;
    free(p);
}

分析:
更新顺序表L的最大容量L.MaxSize,然后释放原来L.data指向的内存空间。

步骤9:

int main() {
    SeqList L;
    InitList(L);
    IncreaseSize(L, 5);
}

分析:
定义了程序的主函数main。首先,创建了一个SeqList类型的变量L,然后调用InitList函数初始化L,最后调用IncreaseSize函数将L的大小增加5个单位。

总结

这篇文章到这里就结束了

谢谢大家的阅读!

如果觉得这篇博客对你有用的话,别忘记三连哦。

我是豌豆射手^,让我们我们下次再见

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

docker 安装 nginx + httpd + php-fpm

原文地址&#xff1a;http://www.taoluyuan.com/index.php/archives/30/#2 展示 1.安装 1.1安装docker 1.2安装nginx 1.3安装apache-httpd 1.4安装php-fpm 2.配置nginx反向代理 httpdphp-fmp 1.安装 1.1安装docker 移除旧的版本&#xff1a; sudo yum remove docker 安装…

redis-plus-plus的安装与使用

本文参考自 redis-plus-plus 官方文档 一、安装 因为redis-plus-plus是基于hiredis封装的&#xff0c;所以需要先安装hiredis&#xff1b; 第一步&#xff1a;安装hiredis # 使用git下载源代码 git clone https://github.com/redis/hiredis.git # 进入源代码主目录 cd hired…

ChatGPT在线网页版

ChatGPT镜像 今天在知乎看到一个问题&#xff1a;“平民不参与内测的话没有账号还有机会使用ChatGPT吗&#xff1f;” 从去年GPT大火到现在&#xff0c;关于GPT的消息铺天盖地&#xff0c;真要有心想要去用&#xff0c;途径很多&#xff0c;别的不说&#xff0c;国内GPT的镜像…

LangChain LangServe 学习笔记

LangChain LangServe 学习笔记 0. 引言1. LangServe 概述2. 特性3. 限制4. 安装5. 示例应用程序6. OpenAPI文档7. Python SDK 客户端8. Playground9. 聊天可运行页面 0. 引言 使用 LangServe 可以立即将您的LLM应用程序变成 API 服务器。 LangServe 使用 FastAPI 构建&#x…

5. Mysql的binlog介绍

参考&#xff1a;InnoDB学习&#xff08;三&#xff09;之BinLog 1. BinLog介绍 BinLog又称为二进制日志&#xff0c;是MySQL服务层的数据日志&#xff0c;MySQL所有的存储引擎都支持BinLog。 BinLog记录了MySQL中的数据更新和可能导致数据更新的事件&#xff0c;可以用于主从…

大数据深度学习:基于Tensorflow深度学习卷积神经网络CNN算法垃圾分类识别系统

文章目录 大数据深度学习&#xff1a;基于Tensorflow深度学习卷积神经网络CNN算法垃圾分类识别系统一、项目概述二、深度学习卷积神经网络&#xff08;Convolutional Neural Networks&#xff0c;简称CNN&#xff09;三、部分数据库架构四、系统实现系统模型部分核心代码模型训…

【C++】模板初阶——泛型编程、函数模板、类模板

1. 泛型编程 如何实现一个通用的交换函数呢&#xff1f; void Swap(int& left, int& right) {int temp left;left right;right temp; } void Swap(double& left, double& right) {double temp left;left right;right temp; } void Swap(char& left…

双向链表的实现(详解)

目录 前言初始化双向链表的结构为双向链表的节点开辟空间头插尾插打印链表尾删头删查找指定位置之后的插入删除pos节点销毁双向链表 前言 链表的分类&#xff1a; 带头 不带头 单向 双向 循环 不循环 一共有 (2 * 2 * 2) 种链表 带头指的是&#xff1a;带有哨兵位节点 哨兵位&a…

关于部署ELK和EFLK的相关知识

文章目录 一、ELK日志分析系统1、ELK简介1.2 ElasticSearch1.3 Logstash1.4 Kibana&#xff08;展示数据可视化界面&#xff09;1.5 Filebeat 2、使用ELK的原因3、完整日志系统的基本特征4、ELK的工作原理 二、部署ELK日志分析系统1、服务器配置2、关闭防火墙3、ELK ElasticSea…

个人笔记目录

目录 一、lora 微调 alpaca 笔记 二、全量微调 Llama2-7b笔记 三、Huggingface trainer 与 from_pretrained简单介绍&#xff08;笔记&#xff09; 四、vscode调试launch.json常用格式 五、huggingface generate函数简介 六、Trl: llama2-7b-hf使用QLora 4bit量化后ds zer…

自动化收集Unity版本更新日志

自动化收集Unity版本更新日志 &#x1f365;功能介绍&#x1f96a;食用手册填写配置开始搜集 &#x1f368;数据展示 &#x1f365;功能介绍 &#x1f4a1;获取指定年份中所有的Unity版本更新日志。 &#x1f4a1;根据指定字符串过滤。 &#x1f4a1;.收集后自动保存成markdow…

Redis队列与Stream

Redis队列与Stream、Redis 6多线程详解 Redis队列与StreamStream总述常用操作命令生产端消费端单消费者消费组消息消费 Redis队列几种实现的总结基于List的 LPUSHBRPOP 的实现基于Sorted-Set的实现PUB/SUB&#xff0c;订阅/发布模式基于Stream类型的实现与Java的集成消息队列问…

OpenHarmony实战开发-FaultLoggerd组件。

简介 Faultloggerd部件是OpenHarmony中C/C运行时崩溃临时日志的生成及管理模块。面向基于 Rust 开发的部件&#xff0c;Faultloggerd 提供了Rust Panic故障日志生成能力。系统开发者可以在预设的路径下找到故障日志&#xff0c;定位相关问题。 架构 Native InnerKits 接口Sig…

向量 | vector;标量 | scalar;矩阵;张量

目录 什么是标量 什么是向量? 向量的3种表达方式 向量的矩阵表示 什么是矩阵 什么是张量 什么是标量 标量只有大小概念,没有方向的概念。通过一个具体的数值就能表达完整。 比如:重量、温度、长度、提及、时间、热量等都数据标量。

绝地求生:杜卡迪“PANIGALE V4 S”摩托车 最全六色测评 游戏内效果展示

PUBG最新联名的杜卡迪摩托车大家都抽到或者换到心仪的颜色了吗 或许有人还在纠结换什么颜色 那么今天给大家带来全网最全颜色测评供大家参考 看看你喜欢哪个吧~ 极速金 2500代币 叛逆玫瑰 2500代币 暮光粉 2500代币 翡翠绿 2500代币 杜卡迪红 1500代币 纯净黑 1500代币 那本期测…

Java开发从入门到精通(二十):Java的面向对象编程OOP:Stream流

Java大数据开发和安全开发 &#xff08;一&#xff09;Java的新特性&#xff1a;Stream流1.1 什么是Stream?1.2 Stream流的使用步骤1.3 获取Stream流1.4 Stream流常见的中间方法1.5 Stream流常见的终结方法 &#xff08;一&#xff09;Java的新特性&#xff1a;Stream流 1.1 …

GNU Radio创建Zadoff-Chu序列C++ OOT块

文章目录 前言一、ZC序列是什么&#xff1f;二、创建自定义的 C OOT 块1、创建 OOT 模块2、创建 OOT 块3、修改 C 文件4、编译及安装 OOT 块 三、测试1、grc 图2、运行结果①、时域图②、时域幅值模图③、IQ 曲线 四、其他五、资源自取 前言 本文实现在 GNU Radio 中创建 Zado…

银河麒麟之PaddleOCR模型部署

一、PaddleOCR简介 PaddleOCR是一个基于飞桨框架开发的开源OCR工具&#xff0c;提供了一系列强大的文本识别功能。PaddleOCR支持多种文本识别任务&#xff0c;包括文字检测、文字识别、文本方向检测等。它具有高效、准确的特点&#xff0c;适用于多种场景下的文本识别需求&…

信息系统项目管理师——管理类计算

风险管理——风险曝光度 风险曝光度概率*影响&#xff0c;概率指风险发生的概率&#xff0c;影响指风险一旦发生&#xff0c;受到影响的项。 题号【GX20061101](61) 知识点[风险曝光度] 风险的成本估算完成后&#xff0c;可以针对风险表中每个风险计算其风险曝光度。某软件小…

Servlet测试1

通过按钮提交get,post请求&#xff0c;并且后端响应数据&#xff0c;显示到前端 当点击get按钮时 是发起Get请求 后端接收到Get请求后&#xff0c;把数据写入到body内 当点击pst按钮时 是发起Post请求 后端接收到Post请求后&#xff0c;把数据写入到body内 之后前端就从bod…