当前位置: 首页 > news >正文

第三十二天:数组

C++ 数组

一、数组基础概念

  1. 定义
    • 数组是一种在 C++ 中用于存储多个相同类型数据元素的数据结构,这些元素在内存中连续存储。
    • 语法:数据类型 数组名[数组大小]; 例如:int numbers[5]; 这里定义了一个名为 numbers 的数组,它可以存储 5 个 int 类型的数据。
  2. 数组的特点
    • 类型一致性:数组中所有元素的数据类型必须相同。这确保了在内存中每个元素占用相同大小的空间,方便系统进行管理和访问。
    • 内存连续性:数组元素在内存中是按顺序连续存储的。这使得通过索引访问元素时效率很高,因为可以根据数组起始地址和元素偏移量快速定位到目标元素。

二、数组的初始化

  1. 静态初始化
    • 完全初始化:在定义数组时,直接为每个元素指定初始值。例如:int numbers[5] = {1, 2, 3, 4, 5}; 这里将数组 numbers 的 5 个元素依次初始化为 1、2、3、4、5。
    • 部分初始化:当初始化列表中的值少于数组元素个数时,剩余元素会根据其数据类型进行默认初始化。对于数值类型(如 intfloat 等),剩余元素会初始化为 0;对于字符类型(char),会初始化为空字符 '\0'。例如:int numbers[5] = {1, 2}; 此时 numbers[0] = 1numbers[1] = 2numbers[2] = 0numbers[3] = 0numbers[4] = 0
  2. 动态初始化(C++11 及以后)
    • 使用花括号进行初始化,编译器可以根据初始化列表的元素个数自动推断数组大小。例如:int numbers[]{1, 2, 3, 4, 5}; 编译器会自动确定 numbers 数组的大小为 5。
    • 这种方式更加灵活,也有助于减少一些潜在的错误,比如数组大小与初始化列表元素个数不匹配的问题。

三、数组元素的访问

  1. 索引(下标)
    • 数组元素通过索引(也称为下标)来访问,索引从 0 开始计数。对于一个具有 n 个元素的数组,其有效索引范围是从 0 到 n - 1。例如,对于数组 int numbers[5];,可以通过 numbers[0] 访问第一个元素,numbers[4] 访问第五个元素。
    • 访问数组元素的语法:数组名[索引]; 例如:int firstNumber = numbers[0]; 这里将 numbers 数组的第一个元素赋值给 firstNumber 变量。
  2. 越界访问
    • 访问数组元素时,必须确保索引在有效范围内。如果访问的索引小于 0 或者大于等于数组大小,就会发生越界访问。例如,对于 int numbers[5];,访问 numbers[5] 就是越界访问。
    • 越界访问会导致未定义行为,这意味着程序的行为是不确定的。可能会导致程序崩溃、数据损坏或产生看似随机的结果。因此,在编写代码时,一定要仔细检查索引值,避免越界访问。

四、数组的常见操作

  1. 遍历数组
    • 使用 for 循环:这是最常见的遍历数组的方式。例如:
int numbers[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++) {std::cout << numbers[i] << " ";
}

在这个例子中,for 循环从 i = 0 开始,每次循环 i 自增 1,直到 i 达到数组大小 5 时停止。在每次循环中,输出数组元素 numbers[i]

  • 使用 while 循环:同样可以实现数组的遍历。例如:
int numbers[5] = {1, 2, 3, 4, 5};
int i = 0;
while (i < 5) {std::cout << numbers[i] << " ";i++;
}

这里通过 while 循环,在 i 小于 5 的条件下,不断输出数组元素并将 i 自增 1。
2. 修改数组元素

  • 可以通过索引直接修改数组元素的值。例如:int numbers[5] = {1, 2, 3, 4, 5}; numbers[2] = 10; 此时,数组 numbers 的第三个元素(索引为 2)的值从 3 被修改为 10。
  1. 查找数组元素
    • 可以通过遍历数组,将每个元素与目标值进行比较,来查找数组中是否存在特定元素。例如,查找数组 numbers 中是否存在值为 3 的元素:
int numbers[5] = {1, 2, 3, 4, 5};
bool found = false;
for (int i = 0; i < 5; i++) {if (numbers[i] == 3) {found = true;break;}
}
if (found) {std::cout << "元素 3 存在于数组中。" << std::endl;
} else {std::cout << "元素 3 不存在于数组中。" << std::endl;
}
  1. 数组排序
    • 常见的排序算法如冒泡排序、选择排序、插入排序等都可以用于对数组进行排序。以冒泡排序为例:
int numbers[5] = {5, 4, 3, 2, 1};
for (int i = 0; i < 5 - 1; i++) {for (int j = 0; j < 5 - i - 1; j++) {if (numbers[j] > numbers[j + 1]) {int temp = numbers[j];numbers[j] = numbers[j + 1];numbers[j + 1] = temp;}}
}
for (int i = 0; i < 5; i++) {std::cout << numbers[i] << " ";
}

冒泡排序通过多次比较相邻元素并交换位置,将最大(或最小)的元素逐步“冒泡”到数组末尾。

五、多维数组

  1. 二维数组
    • 定义:二维数组可以看作是数组的数组,常用于表示具有行和列结构的数据,如矩阵。语法:数据类型 数组名[行数][列数]; 例如:int matrix[3][4]; 定义了一个 3 行 4 列的二维整数数组。
    • 初始化
      • 逐行初始化int matrix[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}; 这种方式将二维数组按行进行初始化。
      • 按顺序初始化int matrix[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; 这种方式按顺序为二维数组的元素赋值,编译器会按行填充元素。
    • 访问元素:通过两个索引来访问二维数组的元素,第一个索引表示行,第二个索引表示列。例如:int element = matrix[1][2]; 这里获取了 matrix 数组第二行第三列的元素(值为 7)。
  2. 多维数组的拓展
    • 除了二维数组,还可以定义三维、四维等多维数组。例如,三维数组可以用于表示立体空间中的数据。定义三维数组的语法:数据类型 数组名[第一维大小][第二维大小][第三维大小]; 例如:int cube[2][3][4]; 表示一个具有 2 层、每层 3 行、每行 4 列的三维数组。

六、数组与函数

  1. 数组作为函数参数
    • 当数组作为函数参数传递时,数组会自动退化为指针。函数定义的语法:返回类型 函数名(数据类型 数组名[], 数组大小参数); 例如:
void printArray(int arr[], int size) {for (int i = 0; i < size; i++) {std::cout << arr[i] << " ";}
}

在调用函数时,可以将数组名作为参数传递,同时传递数组的大小。例如:int numbers[5] = {1, 2, 3, 4, 5}; printArray(numbers, 5);
2. 返回数组的函数

  • 在 C++ 中,函数不能直接返回数组,但可以返回指向数组的指针。不过,使用指针返回数组时需要注意内存管理问题,避免悬空指针等错误。一种更安全的方式是返回 std::vector(C++ 标准库中的动态数组)。例如:
#include <vector>
std::vector<int> createArray() {std::vector<int> arr = {1, 2, 3, 4, 5};return arr;
}

然后可以这样调用函数:std::vector<int> result = createArray();

七、数组的内存管理

  1. 栈上的数组(自动数组)
    • 当数组定义在函数内部时,它是在栈上分配内存的,也称为自动数组。例如:void function() { int numbers[5]; } 当函数 function 执行结束时,数组 numbers 所占用的内存会自动被释放,无需手动管理。
  2. 堆上的数组(动态数组)
    • 使用 new 关键字可以在堆上动态分配数组内存。例如:int* dynamicArray = new int[5]; 这里在堆上分配了一块可以存储 5 个 int 类型数据的内存,并将这块内存的地址赋值给指针 dynamicArray
    • 动态分配的数组在使用完毕后,必须使用 delete[] 来释放内存,以避免内存泄漏。例如:delete[] dynamicArray; 如果不释放动态分配的数组内存,这块内存将一直占用,直到程序结束,从而导致内存泄漏问题。

八、数组的优缺点

  1. 优点
    • 高效的随机访问:由于数组元素在内存中连续存储,可以通过索引快速定位到任意元素,时间复杂度为 O(1)。这使得数组在需要频繁随机访问元素的场景下表现出色,如查找表。
    • 简单直观:数组的概念简单,易于理解和使用。在处理一些基本的数据集合时,数组是一种很自然的选择。
  2. 缺点
    • 大小固定:数组的大小在编译时就必须确定,运行时不能动态改变。这在需要动态调整数据规模的场景下会带来不便,例如在程序运行过程中需要不断添加或删除元素的情况。
    • 插入和删除操作效率低:在数组中间插入或删除元素时,需要移动大量的后续元素,时间复杂度为 O(n),效率较低。相比之下,链表等数据结构在插入和删除操作上更具优势。

通过对 C++ 数组的详细学习,我们了解了数组的基本概念、初始化、访问、常见操作、与函数的交互以及内存管理等方面的知识。在实际编程中,应根据具体需求合理选择和使用数组,充分发挥其优势,同时注意避免其缺点带来的问题。

http://www.dtcms.com/a/359358.html

相关文章:

  • 如何保证redis和mysql的数据一致性
  • Spring Boot 3.x 微服务架构实战指南
  • 基于单片机停车场管理系统/车位管理/智慧停车系统
  • 大模型——xAI 发布 Grok Code Fast 1 编程模型,快、便宜、免费
  • 华为研发投资与管理实践(IPD)读书笔记
  • 第六章:透明度-Transparency《Unity Shaders and Effets Cookbook》
  • 机器视觉学习-day14-绘制图像轮廓
  • 基于Spring Cloud Sleuth与Zipkin的分布式链路追踪实战指南
  • 《深入剖析Kafka分布式消息队列架构奥秘》之Springboot集成Kafka
  • 【重学MySQL】九十四、MySQL请求到响应过程中字符集的变化
  • html添加水印
  • 馈电油耗讲解
  • 特殊符号在Html中的代码及常用标签格式的记录
  • Spring Task快速上手
  • 【多模态】使用LLM生成html图表
  • 【 复习SpringBoot 核心内容 | 配置优先级、Bean 管理与底层原理(起步依赖 + 自动配置) 】
  • 堆排序:高效稳定的大数据排序法
  • Kubernetes 服务发现与健康检查详解
  • 解锁GPU计算潜能:深入浅出CUDA架构与编程模型
  • ESP32学习笔记_Peripherals(5)——SPI主机通信
  • Asible——将文件部署到受管主机和管理复杂的Play和Playbook
  • 局域网中使用Nginx部署https前端和后端
  • Idea启动错误-java.lang.OutOfMemoryError:内存不足错误。
  • Polkadot - ELVES
  • 鸿蒙搭配前端开发:应用端与WEB端交互
  • SCARA 机器人工具标定方法
  • 【算法笔记】算法归纳整理
  • 从零开始的python学习——语句
  • 晶晨线刷工具下载及易错点说明:生成工作流程XML失败
  • 【CVTE】C++开发 (提前批一面)