【数据结构】动态数组(vector)的基本操作,包括插入、删除、扩容、输出、释放内存等。以下是代码的解释和注释:
这段C代码实现了一个动态数组(vector)的基本操作,包括插入、删除、扩容、输出、释放内存等。以下是代码的解释和注释:
// 引入标准输入输出库和标准库函数,用于后续的内存分配和打印输出等操作
#include <stdio.h>
#include <stdlib.h> // 引入时间库,用于生成随机数(这里并未使用,但保留了引入头文件)
#include <time.h> // 定义一个名为vector的结构体,该结构体有三个成员:size表示数组的大小,count表示数组中元素的数量,data是一个指向整型数组的指针,存储数组中的元素
typedef struct vector { int size, count; int *data;
} vector; // getNewVector函数用于创建一个新的动态数组,并返回其指针
vector *getNewVector(int n) { // 使用malloc函数为vector结构体分配内存 vector *p = (vector *)malloc(sizeof(vector)); // 设置新创建的vector的大小为n,元素数量为0,并为data指针分配n个int类型的内存空间 p->size = n; p->count = 0; p->data = (int *)malloc(sizeof(int) * n); // 返回新创建的vector的指针 return p;
} // expand函数用于扩容动态数组,将数组的大小翻倍
int expand(vector *v) { // 检查传入的指针是否为空,如果为空则返回0 if (v == NULL) return 0; // 打印一条消息表示开始扩容 printf("expand v from %d to %d\n", v->size, 2 * v->size); // 使用realloc重新分配足够的内存来存储int类型的2n个元素,并将这些元素的地址赋值给data指针 int *p = (int *)realloc(v->data, sizeof(int) * 2 * v->size); // 如果realloc失败(返回NULL),则返回0;否则,将新分配的内存地址赋值给data,将数组的大小乘以2,并返回1表示扩容成功 if (p == NULL) return 0; v->data = p; v->size *= 2; return 1;
} // insert函数用于在动态数组的指定位置插入一个元素
int insert(vector *v, int pos, int val) { // 检查插入的位置是否合法,如果不合法则返回0 if (pos < 0 || pos > v->count) return 0; // 检查数组是否需要扩容,如果需要扩容但是扩容失败则返回0 if (v->size == v->count && !expand(v)) return 0; // 从数组的末尾开始向前遍历每个元素,将每个元素向后移动一个位置 for (int i = v->count - 1; i >= pos; i--) { v->data[i + 1] = v->data[i]; } // 在指定的位置插入新的元素 v->data[pos] = val; // 将元素数量加1,然后返回1表示插入成功 v->count += 1; return 1;
} // erase函数用于从动态数组中删除指定位置的元素
int erase(vector *v, int pos) { // 检查删除的位置是否合法,如果不合法则返回0 if (pos < 0 || pos >= v->count) return 0; // 从删除位置的下一个位置开始遍历每个元素,将每个元素向前移动一个位置 for (int i = pos + 1; i < v->count; i++) { v->data[i - 1] = v->data[i]; } // 将元素数量减1,然后返回1表示删除成功 v->count -= 1; return 1;
} // 定义一个名为output_vector的函数,它接受一个指向vector结构体的指针作为参数
void output_vector(vector* v) { // 初始化一个整型变量len,用于存储要输出的整数之和 int len = 0; // 遍历vector的大小(即其可以容纳的元素数量) for (int i = 0; i < v->size; i++) { // 在每次循环中,将整数i的值加到len上,同时输出i的值(格式化为三个数字宽) len += printf("%3d", i); } // 输出一个换行符 printf("\n"); // 根据前面输出的整数数量,输出相应数量的短横线(-)以形成一个框架 for (int i = 0; i < len; i++) printf("-"); // 再输出一个换行符 printf("\n"); // 遍历vector中的元素(只遍历实际存在的元素,即count个) for (int i = 0; i < v->count; i++) { // 输出vector中第i个元素的值(格式化为三个数字宽) printf("%3d", v->data[i]); } // 输出一个换行符 printf("\n"); // 输出两个空行,可能是为了创建视觉分隔或提供一些视觉清晰度 printf("\n\n"); // 函数结束,返回无值(void) return;
} // 释放动态数组内存
void clear(vector *v) { // 如果传入的指针为NULL,则直接返回,不进行任何操作 if (v == NULL) return ; // 释放data指针指向的内存空间 free(v->data); // 释放v指针指向的内存空间 free(v); // 返回 return ;
} // 程序从main函数开始执行
int main() { // 使用当前时间作为随机数生成器的种子,这样可以使得每次运行程序时生成的随机数都不同 srand(time(0)); // 定义常量MAX_OP为20,表示要进行的操作次数 #define MAX_OP 20 // 调用getNewVector函数创建一个新的动态数组,并返回指向该数组的指针,数组的大小为2 vector *v = getNewVector(2); // 执行MAX_OP次循环,每次循环都会随机生成一个操作和相应的参数 for (int i = 0; i < MAX_OP; i++) { // 生成一个介于0到3之间的随机数,这个随机数将用于决定执行哪种操作 int op = rand() % 4, pos, val, ret; // 根据随机数决定执行哪种操作 switch (op) { // 如果操作是0、1或2,表示要进行插入操作 case 0: case 1: case 2: // 生成一个介于0到(数组大小+1)之间的随机数,作为插入位置 pos = rand() % (v->count + 2); // 生成一个介于0到99之间的随机数,作为要插入的值 val = rand() % 100; // 调用insert函数进行插入操作,并把返回值保存在ret变量中 ret = insert(v, pos, val); // 输出插入操作的信息,包括插入的值、插入的位置以及插入是否成功的返回值 printf("insert %d at %d to vector = %d\n", val, pos, ret); break; // 如果操作是3,表示要进行删除操作 case 3: // 生成一个介于0到(数组大小+1)之间的随机数,作为删除位置 pos = rand() % (v->count + 2); // 调用erase函数进行删除操作,并把返回值保存在ret变量中 ret = erase(v, pos); // 输出删除操作的信息,包括删除位置以及删除是否成功的返回值 printf("erase item at %d in vector = %d\n", pos, ret); break; } // 输出当前动态数组的内容 output_vector(v); } // 调用clear函数释放动态数组所占用的内存空间 clear(v); // 程序正常结束,返回0 return 0;
}
这段代码实现了一个简单的动态数组(vector),包含插入、删除和打印数组元素的功能。下面是各个函数的功能解释:
getNewVector(int n)
:这个函数创建了一个新的动态数组,并为其分配了指定数量的整数存储空间。它返回一个指向新创建的动态数组的指针。expand(vector *v)
:这个函数用于将动态数组的存储空间扩大一倍。如果当前的存储空间已经足够,那么它什么都不做。否则,它会使用realloc
函数来重新分配两倍于当前大小的存储空间,并将旧的数据复制到新的存储空间。如果扩大存储空间失败,它会返回0,否则返回1。insert(vector *v, int pos, int val)
:这个函数在动态数组中插入一个新的元素。它首先检查插入的位置是否有效,然后检查是否需要扩大存储空间。如果需要扩大存储空间且扩大操作失败,它会返回0。否则,它会将数组中的所有元素向后移动一位,然后在指定的位置插入新的元素。最后,它会返回1表示插入成功。erase(vector *v, int pos)
:这个函数从动态数组中删除一个元素。它首先检查删除的位置是否有效,然后删除元素并返回1表示删除成功。output_vector(vector *v)
:这个函数打印动态数组的所有元素和它们的位置(包括空位)。clear(vector *v)
:这个函数释放动态数组的内存空间。
相关文章:
【数据结构】动态数组(vector)的基本操作,包括插入、删除、扩容、输出、释放内存等。以下是代码的解释和注释:
这段C代码实现了一个动态数组(vector)的基本操作,包括插入、删除、扩容、输出、释放内存等。以下是代码的解释和注释: // 引入标准输入输出库和标准库函数,用于后续的内存分配和打印输出等操作 #include <stdio.…...

[unity]三角形顶点顺序
序 详见官方文档:Unity - Manual: Mesh data (unity3d.com) Topology:拓扑结构 翻译: 拓扑描述网格具有的面类型。 网格的拓扑定义了索引缓冲区的结构,索引缓冲区又描述了顶点位置如何组合成面。每种类型的拓扑都使用索引数组中…...

【python爬虫】14.Scrapy框架讲解
文章目录 前言Scrapy是什么Scrapy的结构Scrapy的工作原理 Scrapy的用法明确目标与分析过程代码实现——创建项目代码实现——编辑爬虫代码实现——定义数据代码实操——设置代码实操——运行 复习 前言 前两关,我们学习了能提升爬虫速度的进阶知识——协程…...

功率放大器主要作用是什么呢
功率放大器是一种电子设备,主要作用是将输入信号的功率增加到更高的水平,以便能够驱动高功率负载。在许多应用中,信号源产生的信号往往具有较低的功率,无法直接满足一些要求较高的设备或系统的需求。而功率放大器则可以增强信号的…...
SpringBoot ApplicationEvent详解
ApplicationStartingEvent 阶段 LoggingApplicationListener#onApplicationStartingEvent 初始化日志工厂,LoggingSystemFactory接口,可以通过spring.factories进行定制 可以通过System.setProperty("org.springframework.boot.logging.LoggingSystem",&q…...
WebSocket 报java.io.IOException: 远程主机强迫关闭了一个现有的连接。
在客户端强制关闭时,或者窗口强制关闭时,后端session没有关闭。 有时还会报:java.io.EOFException: 这个异常 前端心跳没有收到信息,还在心跳。 CloseReason close new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, &…...

关于git约定式提交IDEA
背景 因为git提交的消息不规范导致被乱喷,所以领导统一规定了约定式提交 官话 约定式提交官网地址 约定式提交规范是一种基于提交信息的轻量级约定。 它提供了一组简单规则来创建清晰的提交历史; 这更有利于编写自动化工具。 通过在提交信息中描述功能…...

【计算机网络】http协议
目录 前言 认识URL URLEncode和URLDecode http协议格式 http方法 GET POST GET与POST的区别 http状态码 http常见header 简易的http服务器 前言 我们在序列化和反序列化这一章中,实现了一个网络版的计算器。这个里面设计到了对协议的分析与处…...
仓库太大,clone 后,git pull 老分支成功,最新分支失败
由于 git 仓库太大,新加入的小伙伴在拉取时,无法切换到最新的分支,报错如下: fetch-pack: unexpected disconnect while reading sideband packet fatal: early EOF fatal: fetch-pack: invalid index-pack output在此记录解决步…...
javafx Dialog无法关闭
// 生成二维码图片String qrCodeText "https://example.com";DialogPane grid new DialogPane();grid.setPadding(new Insets(5));VBox vBox new VBox();vBox.setAlignment(Pos.CENTER);Image qrCodeImage generateQRCodeImage(qrCodeText);ImageView customImag…...

vue3中TCplayer应用
环境win10:vitevue3elementUI 1 安装 npm install tcplayer.js2 使用 <template><div><video id"player-container-id" width"414" height"270" preload"auto" playsinline webkit-playsinline></video>&l…...

算法通关村14关 | 数据流中位数问题
1. 数据流中位数问题 题目 LeetCode295: 中位数是有序列表中间的数,如果列表长度是偶数,中位数是中间两个数的平均值, 例如:[2,3,4]的中位数是3, [2,3]中位数是(23)/ 2 2.5 设计一个数据结构: …...
工厂模式 与 抽象工厂模式 的区别
工厂模式: // 抽象产品接口 interface Product {void showInfo(); }// 具体产品A class ConcreteProductA implements Product {Overridepublic void showInfo() {System.out.println("This is Product A");} }// 具体产品B class ConcreteProductB impl…...

安装虚拟机+安装/删除镜像
安装虚拟机 注意,官网可能无法登录,导致无法从官网下载,就自己去网上搜靠谱的下载,我用的16.2.3 删除镜像 Vm虚拟机怎么删除已经创建的系统?Vm虚拟机创建好之后iso删除方法 - 系统之家 (xitongzhijia.net) 安装镜像…...

MySQL的内置函数复合查询内外连接
文章目录 内置函数时间函数字符串函数数学函数其他函数 复合查询多表笛卡尔积自连接在where中使用子查询多列子查询在from中使用子查询 内连接外连接左外连接右外连接 内置函数 时间函数 函数描述current_date()当前日期current_time()当前时间current_timestamp()当前时间戳…...

操作系统(OS)与系统进程
操作系统(OS)与系统进程 冯诺依曼体系结构操作系统(Operator System)进程基本概念进程的描述(PCB)查看进程通过系统调用获取进程标示符(PID)通过系统调用创建进程(fork)进程状态&…...
防重复提交:自定义注解 + 拦截器(HandlerInterceptor)
防重复提交:自定义注解 拦截器(HandlerInterceptor) 一、思路: 1、首先自定义注解; 2、创建拦截器实现类(自定义类名称),拦截器(HandlerInterceptor); 3…...

Excel中将文本格式的数值转换为数字
在使用excel时,有时需要对数字列进行各种计算,比如求平均值,我们都知道应该使用AVERAGE()函数,但是很多时候结果却“不尽如人意”。 1 问题: 使用AVERAGE函数: 结果: 可以看到单元格左上角有个…...

uni-app开发小程序中遇到的map地图的点聚合以及polygon划分区域问题
写一篇文章来记录以下我在开发小程序地图过程中遇到的两个小坑吧,一个是点聚合,用的是joinCluster这个指令,另一个是polygon在地图上划分多边形的问题: 1.首先说一下点聚合问题,由于之前没有做过小程序地图问题&#…...

【笔记】软件测试的艺术
软件测试的心理学和经济学 测试是为发现错误而执行程序的过程,所以它是一个破坏性的过程,测试是一个“施虐”的过程。 软件测试的10大原则 1、测试用例需要对预期输出的结果有明确的定义 做这件事的前提是能够提前知晓需求和效果图,如果不…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...