C++数组全面讲解

ops/2024/10/19 15:42:53/

文章目录

  • 数组
    • 介绍
      • 数组的特点
      • 数组的优缺点
      • 数组和其他数据结构的比较
    • 静态数组与动态数组的详细讲解
      • 一、静态数组
        • 1. 一维数组
          • 声明与初始化
          • 注意事项
          • 特点
        • 2. 二维数组
          • 声明与初始化
          • 注意事项
          • 特点
        • 3. 三维数组
          • 声明与初始化
          • 注意事项
          • 特点
      • 二、动态数组
        • 1. 一维数组
          • 声明与初始化
          • 注意事项
          • 特点
        • 2. 二维数组
          • 声明与初始化
          • 注意事项
          • 特点
        • 3. 三维数组
          • 声明与初始化
          • 注意事项
          • 特点
      • 总结

数组

介绍

​ 数组是一种基本的数据结构,它用于存储固定大小的同类型元素集合。数组的特点包括:

数组的特点

  • 线性结构

​ 数组是一种线性数据结构,因为其元素在内存中是连续存储的。每个元素都可以用过一个索引(或下标)来访问,这个索引表示了元素在数组中的位置。

  • 固定大小

​ 数组的大小必须在定义的时候指定,并且在运行时无法改变,这意味着数组一旦创建,其容量九四固定的。

  • 元素类型一致c

​ 由于数组中的元素在内容中是连续存储的,可以通过索引实现常数时间(O(1))的随机方法问。这意味着我们可以直接访问任何位置的元素,而不需要遍历其他元素。

  • 内存分配

​ 数组通常是在栈上分配内存(对于局部数组),或者在堆上分配内存(对于动态数组)。栈上的数组在作用域结束时会自动释放,而在堆上分配的数组需要手动释放。

  • 空间效率

​ 由于数组的元素在内存空格键中是连续存储的,所以数组具有良好的空间局部性,这有助于提高缓存的效率和系统的性能。

  • 数组的常见操作
    • 访问元素:通过索引直接访问
    • 遍历:通过循环遍历数组的所有元素
    • 修改元素:通过索引修改数组中某个位置的值
    • 初始化:在声明时进行初始化,或者在之后通过循环或其他方式进行初始化。

数组的优缺点

优点:

  • 高效的随机访问:可以在常数时间内访问任何位置的元素
  • 简单的实现:实现简单,易于理解和使用

缺点:

  • 固定大小:
  • 插入和删除:
  • 内存管理:

数组和其他数据结构的比较

  • 与链表比较:链表的插入和删除操作更高效(O(1)),但随机访问的时间复杂度是O(n),而数组提供常数时间的随机访问。
  • 与哈希表比较:哈希表提供更高效的查找操作,但没有数组的顺序性和索引访问优势。
  • 与树结构比较:树结构提供了有序数据存储和高效的插入/删除操作,但数组提供更简洁的实现和更好的内存局部性。

静态数组与动态数组的详细讲解

在 C++ 中,数组分为静态数组和动态数组。静态数组在编译时分配内存,大小固定;而动态数组在运行时分配内存,大小可以动态调整。下面我们分别讨论一维、二维和三维数组的静态和动态实现。

一、静态数组

1. 一维数组
声明与初始化
  • 声明:类型 数组名[数组大小];
  • 初始化:可以在声明时初始化,例如 int arr[5] = {1, 2, 3, 4, 5};
#include <iostream>int main() {int arr[5] = {1, 2, 3, 4, 5}; // 声明并初始化一个静态一维数组for (int i = 0; i < 5; i++) {std::cout << arr[i] << " ";}return 0;
}

运行结果:
运行结果

注意事项
  • 数组大小必须在编译时确定。
  • 数组元素在内存中是连续存储的。
  • 如果不完全初始化,未被显式初始化的元素会自动被初始化为零。
特点
  • 简单且高效,内存分配和释放由编译器自动管理。
  • 适用于数组大小固定且编译时已知的场景。
2. 二维数组
声明与初始化
  • 声明:类型 数组名[行数][列数];
  • 初始化:可以在声明时初始化,例如 int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
#include <iostream>int main() {int arr[2][3] = {{1, 2, 3}, {4, 5, 6}}; // 声明并初始化一个静态二维数组for (int i = 0; i < 2; i++) {for (int j = 0; j < 3; j++) {std::cout << arr[i][j] << " ";}std::cout << std::endl;}return 0;
}

运行结果:
运行结果描述

注意事项
  • 与一维数组类似,数组大小在编译时确定。
  • 存储方式是行优先,即按行连续存储。
特点
  • 适用于需要矩阵或表格形式存储数据的场景。
3. 三维数组
声明与初始化
  • 声明:类型 数组名[深度][行数][列数];
  • 初始化:可以在声明时初始化,例如 int arr[2][2][3] = {{{1, 2, 3}, {4, 5, 6}}, {{7, 8, 9}, {10, 11, 12}}};
#include <iostream>int main() {int arr[2][2][3] = {{{1, 2, 3}, {4, 5, 6}},{{7, 8, 9}, {10, 11, 12}}}; // 声明并初始化一个静态三维数组for (int i = 0; i < 2; i++) {for (int j = 0; j < 2; j++) {for (int k = 0; k < 3; k++) {std::cout << arr[i][j][k] << " ";}std::cout << std::endl;}std::cout << std::endl;}return 0;
}

运行结果:
运行结果

注意事项
  • 与二维数组类似,三维数组也是按行优先存储。
  • 需要更多内存,因此可能在栈上占用较大空间。
特点
  • 适用于需要处理多维数据的场景,例如图像处理或物理模拟。

二、动态数组

1. 一维数组
声明与初始化
  • 动态数组使用指针进行管理,常用 new 操作符来动态分配内存。
  • 声明:类型* 数组名 = new 类型[数组大小];
#include <iostream>int main() {int n = 5;int* arr = new int[n]; // 声明并动态分配一个一维数组for (int i = 0; i < n; i++) {arr[i] = i + 1;}for (int i = 0; i < n; i++) {std::cout << arr[i] << " ";}delete[] arr; // 释放动态分配的内存return 0;
}

运行结果:
运行结果

注意事项
  • 必须使用 delete[] 释放动态分配的内存,否则会导致内存泄漏。
  • 数组大小可以在运行时确定。
特点
  • 灵活,可在运行时根据需要调整大小。
  • 适用于需要动态调整数组大小的场景。
2. 二维数组
声明与初始化
  • 声明:类型** 数组名 = new 类型*[行数]; 然后为每一行分配列的内存。
#include <iostream>int main() {int rows = 2, cols = 3;int** arr = new int*[rows]; // 声明并动态分配一个二维数组for (int i = 0; i < rows; i++) {arr[i] = new int[cols];}// 初始化int count = 1;for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {arr[i][j] = count++;}}// 打印数组for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {std::cout << arr[i][j] << " ";}std::cout << std::endl;}// 释放内存for (int i = 0; i < rows; i++) {delete[] arr[i];}delete[] arr;return 0;
}

运行结果:
运行结果

注意事项
  • 必须为每一行单独分配和释放内存。
  • 处理较大的二维数组时,要小心内存泄漏。
特点
  • 动态调整行列数,适用于运行时需要动态改变矩阵大小的场景。
3. 三维数组
声明与初始化
  • 声明:类型*** 数组名 = new 类型**[深度]; 然后为每个“面”分配二维数组的内存。
#include <iostream>int main() {int depth = 2, rows = 2, cols = 3;int*** arr = new int**[depth]; // 声明并动态分配一个三维数组for (int i = 0; i < depth; i++) {arr[i] = new int*[rows];for (int j = 0; j < rows; j++) {arr[i][j] = new int[cols];}}// 初始化int count = 1;for (int i = 0; i < depth; i++) {for (int j = 0; j < rows; j++) {for (int k = 0; k < cols; k++) {arr[i][j][k] = count++;}}}// 打印数组for (int i = 0; i < depth; i++) {for (int j = 0; j < rows; j++) {for (int k = 0; k < cols; k++) {std::cout << arr[i][j][k] << " ";}std::cout << std::endl;}std::cout << std::endl;}// 释放内存for (int i = 0; i < depth; i++) {for (int j = 0; j < rows; j++) {delete[] arr[i][j];}delete[] arr[i];}delete[] arr;return 0;
}

运行结果:
运行结果

注意事项
  • 三维数组需要更多的内存管理操作。
  • 可能导致复杂的内存泄漏问题,需要小心处理内存释放。
特点
  • 适用于需要多维度数据处理的场景,尤其是需要在运行时动态调整每个维度大小的情况。

总结

  • 静态数组 简单、高效,但受限于编译时的固定大小,适合处理大小已知且固定的数据集。
  • 动态数组 提供了更大的灵活性,能够在运行时分配和释放内存,适合处理大小不确定或需要动态调整的场景。

静态数组适合于内存占用较小、大小固定的场景,而动态数组更适合内存管理要求严格或者需要处理大数据的应用。


http://www.ppmy.cn/ops/90068.html

相关文章

Element UI 如何配置文件来设置全局的语言选项。

Element UI 允许你通过配置文件来设置全局的语言选项&#xff0c;这样你可以方便地切换组件的语言。以下是如何配置 Element UI 以设置全局语言选项的步骤&#xff1a; 1. 安装 Element UI 确保你已经安装了 Element UI。 npm install element-ui --save2. 引入语言包 Elem…

AWS域名注册:AWS 是否可以注册HK域名?

AWS&#xff08;Amazon Web Services&#xff09;本身并不直接提供域名注册服务&#xff0c;但它通过其服务Amazon Route 53提供域名注册功能&#xff0c;九河云来和你详细说说域名注册的一些事项吧。通过Amazon Route 53&#xff0c;你可以注册各种顶级域名&#xff08;TLD&am…

机器学习用python还是R,哪个更好?

选择使用Python还是R进行机器学习取决于多个因素,包括您的具体需求、项目要求、个人偏好以及团队的技能水平。以下是一些关键点,可以帮助您做出决定: Python的优势 广泛使用:Python是目前最流行的编程语言之一,特别是在数据科学和机器学习领域。它有一个庞大的社区和丰富…

解决报错:AssertionError: Torch not compiled with CUDA enabled

首先查看自己的cuda是否可用 torch.cuda.is_available()这里我的cuda是不适配torch的&#xff0c;所以需要重新安装适配的torch 查看自己的cuda版本 方法1 方法2 在cmd处输入nvidia-smi 这样可以找到的自己的CUDA版本安装符合自己版本的pytorch 进入pytorch官网https://pyt…

深入探究 C 字符串

平时处理 C 和 C 字符串的时候有下面几个问题困扰着我&#xff1a; C 的字符串与普通数组有什么不同&#xff1f;C 中字符串字面量为什么是 const char * &#xff1f;字符串字面量的赋值操作需要拷贝吗&#xff1f; 在这篇文章中我想简单解答一下上面的问题。如果你跟我一样…

【Linux】权限理解

目录 1. Linux权限的概念2.文件类型和访问权限2.1 文件访问者的分类2.2 文件属性 3. 文件权限值的表示方法4. 文件访问权限的相关设置方法4.1 chmod----设置文件的访问权限4.2 chown----修改文件的拥有者/所属组4.3 chgrp----修改文件或目录的所属组4.4 umask----查看或修改文件…

redis在Django当中的使用方法

redis在Django中怎么使用 在utils/redis_pool.py文件 创建 import redisPOOL redis.ConnectionPool(max_connections10, decode_responsesTrue)在哪里用&#xff0c;导入用即可 from utils.redis_pool import POOL import redis# --------------------- class pooltestVie…

搭建基于树莓派的Linux学习环境(TODO)

主要是想学一下Linux内核&#xff0c;所以搭一套环境&#xff0c;其实有几个选择&#xff0c;都是我买了板子的。 首先是正点原子的RK3568&#xff0c;最早是想弄安卓&#xff0c;但是SDK的大小真的把我劝退了&#xff0c;动不动几百个G的空间&#xff0c;还有就是保底16个G的…