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

第三十二天:数组

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.xdnf.cn/news/19317.html

相关文章:

  • 刷算法题-数组-02
  • 关于Ctrl+a不能全选的问题
  • Wi-Fi技术——OSI模型
  • VS安装 .NETFramework,Version=v4.6.x
  • React Hooks useMemo
  • [强网杯2019]随便注-----堆叠注入,预编译
  • centos7挂载iscis存储操作记录
  • postman 用于接口测试,举例
  • postman带Token测试接口
  • DAY50打卡
  • Redis 持久化 AOF 与 RDB 的区别
  • Ruoyi-vue-plus-5.x第二篇MyBatis-Plus数据持久层技术:2.1 MyBatis-Plus核心功能
  • audioLDM模型代码阅读(五)—— pipeline
  • Python学习大集合:基础与进阶、项目实践、系统与工具、Web 开发、测试与运维、人工智能(视频教程)
  • 电力电子技术知识学习-----晶闸管
  • VSCode中使用Markdown
  • 从零开始学炒股
  • cordova+umi 创建项目android APP
  • PythonDay42
  • KNN算法常见面试题
  • C数据结构:排序
  • 第25章学习笔记|额外的提示、技巧与技术(PowerShell 实战版)
  • Qt Core 之 QString
  • PyTorch 张量(Tensor)详解:从基础到实战
  • 【深度学习】配分函数:近似最大似然与替代准则
  • python复杂代码如何让ide自动推导提示内容
  • 编写Linux下usb设备驱动方法:disconnect函数中要完成的任务
  • More Effective C++ 条款20:协助完成返回值优化(Facilitate the Return Value Optimization)
  • 每日算法题【栈和队列】:栈和队列的实现、有效的括号、设计循环队列
  • [软考中级]嵌入式系统设计师—考核内容分析