【数据结构】动态数组(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),包含插入、删除和打印数组元素的功能。下面是各个函数的功能解释:

  1. getNewVector(int n):这个函数创建了一个新的动态数组,并为其分配了指定数量的整数存储空间。它返回一个指向新创建的动态数组的指针。
  2. expand(vector *v):这个函数用于将动态数组的存储空间扩大一倍。如果当前的存储空间已经足够,那么它什么都不做。否则,它会使用 realloc 函数来重新分配两倍于当前大小的存储空间,并将旧的数据复制到新的存储空间。如果扩大存储空间失败,它会返回0,否则返回1。
  3. insert(vector *v, int pos, int val):这个函数在动态数组中插入一个新的元素。它首先检查插入的位置是否有效,然后检查是否需要扩大存储空间。如果需要扩大存储空间且扩大操作失败,它会返回0。否则,它会将数组中的所有元素向后移动一位,然后在指定的位置插入新的元素。最后,它会返回1表示插入成功。
  4. erase(vector *v, int pos):这个函数从动态数组中删除一个元素。它首先检查删除的位置是否有效,然后删除元素并返回1表示删除成功。
  5. output_vector(vector *v):这个函数打印动态数组的所有元素和它们的位置(包括空位)。
  6. clear(vector *v):这个函数释放动态数组的内存空间。

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

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

相关文章

Python小知识 - 使用Python进行数据分析

使用Python进行数据分析 数据分析简介 数据分析&#xff0c;又称为信息分析&#xff0c;是指对数据进行综合处理、归纳提炼、概括总结的过程&#xff0c;是数据处理的第一步。 数据分析的目的是了解数据的内在规律&#xff0c;为数据挖掘&#xff0c;并应用于商业决策、科学研究…

Pytorch.tensor 相关用法

Torch.tensor.backward()方法的使用举例 理解optimizer.zero_grad(), loss.backward(), optimizer.step()的作用及原理 Autograd: 自动求导 import torchatorch.randn(2,2) # tensor默认requires_gradFalse a((a*3)/(a-1)) print(a.requires_grad) print(a.grad_fn) # leaf …

运行速度高达1.8GHz可编程采集网关

今天介绍下BL304这个设备。嵌入式ARM控制器BL304系列是一款专为工业控制领域设计的坚固型工控设备。它采用NXP公司的处理器I.MX8M Mini四核64位处理器&#xff0c;搭配四核 Cortex-A53单核Cortex-M4构架&#xff0c;运行速度高达1.8GHz&#xff0c;具有高度的稳定性和可靠性。 …

从0到1学会Git(第二部分):Git的本地操作和管理

写在前面:本文介绍了在本地仓库进行文件的处理以及本地的合并等操作。 前置知识:文件可以处在三个区域&#xff0c;分别为工作区&#xff0c;暂存区和本地仓库&#xff0c;我们此文的目标即是将文件存储在本地仓库中。我们可以将文件的区域理解为&#xff0c;cpu中&#xff0c…

计算机视觉主要任务

计算机视觉&#xff1a;使用计算机及相关设备对生物视觉的一种模拟。 主要包含6大任务&#xff0c;图像分类&#xff0c;目标检测&#xff0c;目标跟踪&#xff0c;语义分割&#xff0c;实例分割&#xff0c;影像重构。 图像分类&#xff1a;根据图像信息中所反映的不同特征&am…

数据结构与算法复杂度介绍

目录 一、基本概念 二、时间复杂度 【2.1】时间复杂度概念 【2.2】大O的渐进表示法 【2.3】举例时间复杂度计算 三、空间复杂度 一、基本概念 数据结构&#xff1a;相互之间存在一种或者多种特定关系的数据元素的集合。在逻辑上可以分为线性结构&#xff0c;散列结构、树…

Redis List类型命令 - Set类型命令 - SortedSet类型命令

目录 List类型 什么是双向链表呢&#xff1f; List类型的特征&#xff1a; List的常用命令 LPUSH和RPUSH的区别&#xff1a; LPOP和RPOP的区别&#xff1a; LPUSH和RPUSH的使用 LPOP和RPOP的使用 LRANGE key star end&#xff1a;返回一段距离范围内所有的元素 BLPOP…

最小生成树Kruskal、Prim算法C++

什么是最小生成树 连通图&#xff1a; 在无向图中&#xff0c;若从顶点v1到顶点v2有路径&#xff0c;则称顶点v1和顶点v2是连通的。如果图中任意一对顶点都是连通的&#xff0c;则称此图为连通图。 生成树&#xff1a; 一个连通图的最小连通子图称作为图的生成树。有n个顶点的…

Pytorch 的基本概念和使用场景介绍

文章目录 一、基本概念1. 张量&#xff08;Tensor&#xff09;2. 自动微分&#xff08;Autograd&#xff09;3. 计算图&#xff08;Computation Graph&#xff09;4. 动态计算图&#xff08;Dynamic Computation Graph&#xff09;5. 变量&#xff08;Variable&#xff09; 二、…

【用unity实现100个游戏之8】用Unity制作一个炸弹人游戏

文章目录 前言素材开始一、绘制地图二、玩家设置三、玩家移动四、玩家四方向动画运动切换 五、放置炸弹六、生成爆炸效果七、墙壁和可破坏障碍物的判断八、道具生成和效果九、玩家死亡十、简单的敌人AI十一、简单敌人AI十二、随机绘制地图十三、虚拟摇杆 最终效果待续源码完结 …

2023年行研行业研究报告

第一章 行业概述 1.1 行研行业 行业定义为同一类别的经济活动&#xff0c;这涉及生产相似产品、应用相同生产工艺或提供同类服务的集合&#xff0c;如食品饮料行业、服饰行业、机械制造行业、金融服务行业和移动互联网行业等。 为满足全球金融业的需求&#xff0c;1999年8月…

设计模式-单例模式Singleton

单例模式 单例模式 (Singleton) (重点)1) 为什么要使用单例2) 如何实现一个单例2.a) 饿汉式2.b) 懒汉式2.c) 双重检查锁2.d) 静态内部类2.e) 枚举类2.f) 反射入侵2.g) 序列化与反序列化安全 3) 单例存在的问题3.a) 无法支持面向对象编程 单例模式 (Singleton) (重点) 一个类只…

Linux之autofs自动挂载服务

目录 Linux之autofs自动挂载服务 产生原因 安装 配置文件分析 文件路径 作用 etc/auto.master文件内容格式 挂载参数 案例 案例1 --- 服务器创建共享目录&#xff0c;客户端实现自动挂载 案例2 --- 自动挂载光盘 Linux之autofs自动挂载服务 产生原因 在一般NFS文件系…

java 从resource下载excel打不开

GetMapping("/download/template")public void template(HttpServletResponse response) throws IOException {ServletOutputStream outputStream response.getOutputStream();InputStream inputStream null;try {//从resource获取excel文件流inputStream getClas…

$attrs,$listeners

vue实现组件通信的方式有&#xff1a; 父子通信 父组件向子组件传递通过props定义各个属性来传递&#xff0c;子组件向父组件传递通过$emit触发事件 ref也可以访问组件实例跨级通信 vuex bus provide / inject $attrs / $listeners解释 $attrs / $listeners $attrs 将父组件中…

python selenium 自动化登录页面

去掉自动化标识&#xff0c;绕过js&#xff0c;绕过ip import time from selenium import webdriver from selenium.webdriver.chrome.options import Options# 去掉自动化标识&#xff0c;绕过js option Options() option.add_experimental_option(excludeSwitches, [enable…

服务端请求伪造(SSRF)及漏洞复现

文章目录 渗透测试漏洞原理服务端请求伪造1. SSRF 概述1.1 SSRF 场景1.1.1 PHP 实现 1.2 SSRF 原理1.3 SSRF 危害 2. SSRF 攻防2.1 SSRF 利用2.1.1 文件访问2.1.2 端口扫描2.1.3 读取本地文件2.1.4 内网应用指纹识别2.1.5 攻击内网Web应用 2.2 SSRF 经典案例2.2.1 访问页面2.2.…

自然语言处理实战项目17-基于多种NLP模型的诈骗电话识别方法研究与应用实战

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下自然语言处理实战项目17-基于NLP模型的诈骗电话识别方法研究与应用&#xff0c;相信最近小伙伴都都看过《孤注一掷》这部写实的诈骗电影吧&#xff0c;电影主要围绕跨境网络诈骗展开&#xff0c;电影取材自上万起真…

ASP.NET Core 的 HttpContex

HttpContext HttpContext 类封装了HTTP Request 和 HTTP Response。 当收到一条HTTP Request 请求时&#xff0c;就会实例化一个HttpContext对象。HttpContext对象可以被中间件访问。 注意&#xff1a;HttpContext 不是线程安全的。 读取 HttpContext 的值 从Razer Page 读取…

基于Java+SpringBoot+Vue前后端分离善筹网(众筹)设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…