C++数组全面讲解

news2024/11/16 9:31:33

文章目录

  • 数组
    • 介绍
      • 数组的特点
      • 数组的优缺点
      • 数组和其他数据结构的比较
    • 静态数组与动态数组的详细讲解
      • 一、静态数组
        • 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.coloradmin.cn/o/1984156.html

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

相关文章

HarmonyOS鸿蒙开发学习:鸿蒙基础-基础环境-ArkTS-组件-样式

鸿蒙基础-基础环境-ArkTS-组件-样式 DevEcoStudio编辑器下载链接 链接: https://pan.baidu.com/s/18C9i35YPh4GsHpbSif8KQw?pwdd6e9 提取码: d6e9 安装教程 下载对应的版本 windowsmac英特尔mac Arm API12 的编辑器 API12的模拟器(mac英特尔安装API11) Mac Arm芯片版本安装…

CCPC 2024, Shanghai

2024.8.5 12:00————17:00 CCPC 2024, Shanghai [A - 无线网络整点栅格统计](https://atcoder.jp/contests/math-and-algorithm/tasks/abc204_d?langen)[E - 无线软件日](https://atcoder.jp/contests/abc265/tasks/abc265_a?langen)[J - 极简合数序列](https://atcoder.…

【面试题】合井K个升序链表

合井K个升序链表 仅供面试学习 给定一个链表数组&#xff0c;每个链表都已经按升序排列。将所有链表合并到一个升序链表中&#xff0c;并返回合并后的链表。以下是详细的解题步骤和 Python 代码示例。 一、问题描述 将多个升序链表合并为一个升序链表。要求算法能有效处理链表…

Codeforces Round 871 (Div. 4)(A~H)

比赛链接 Dashboard - Codeforces Round 871 (Div. 4) - Codeforces A. Love Story 找到与codeforces 有多少个不同的字符。 #include<bits/stdc.h> #define int long long #define TEST int T; cin >> T; while (T--) #define ios ios::sync_with_stdio(fals…

人大金仓安装图文

1.下载 通过百度网盘分享的文件&#xff1a;人大金仓安装图文 链接&#xff1a;https://pan.baidu.com/s/1imt0KsyVXQALp_icEMoDpQ 提取码&#xff1a;zwef --来自百度网盘超级会员V3的分享 2.安装

CTFHub~RCE远程代码执行

0X01eval执行 # 进来我们直接看到了代码&#xff0c;大致意思就是传入一个参数cmd# 所以我们直接使用蚁剑进行连接&#xff0c;看一下能否成功# 接下来我们直接找出flag0X02文件包含 # 打开页面发现一大堆代码 大体意思是如果file中没有flag字符串就执行下面的include $_GET[…

【linux深入剖析】线程控制 | 多线程

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 1. 创建线程2. POSIX线程…

基于Kubernetes v1.25.0和Docker部署高可用集群(说明篇)

目录描述 Kubernetes组件说明 特定接口CRI、CNI、CSI Kubernetes v1.25集群创建方案选择 一、Kubernetes组件说明 Docker 的运行机制 运行机制详解&#xff1a; docker client&#xff1a;命令行输入的docker命令就是一个docker客户端 docker Engine&#xff1a;Engine也…

Java: 死锁问题详解(5000字)

文章目录 死锁的出现场景1. 一个线程一把锁,这个线程针对这把锁,连续加锁了两次2. 两个线程,两把锁3. N个线程 , M个锁4. 内存可见性为什么会出现内存可见性问题呢?解决方法 volatile关键字 总结synchronized:死锁的四个必要条件(缺一不可)[重点]:内存可见性问题: 死锁的出现场…

PCL安装与配置(PCL1.9.1+MSVC2017)

为了和我的VS的版本VS 2017对应&#xff0c;PCL下载的也是msvc_2017,PCL msvc2017最新的则是1.901版本&#xff0c;我们就以PCL 1.9.1为例了。&#xff08;如果你的vs是2019和2022&#xff0c;一定要注意PCL的版本&#xff09;。 一、下载PCL 我们打开PCL的github下载地址&am…

GDB调试器

GDB调试器 GDB的主要功能 常见命令 3、实战 1、生成能调试的执行文件&#xff08;一定要加-g&#xff09; 第一个是不能调试的 第二个这样加了-g才能进行调试 如果没加-g 执行gdb 执行文件&#xff08;会报下面这个 &#xff09; 像这样才是正常的 执行 gdb a_yes_g 这…

SSM计算机组成原理课程平台-计算机毕设定制-附项目源码(可白嫖)50168

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…

金融行业到底该选择什么样的FTP替代方案?

2018年以来&#xff0c;受“华为、中兴事件”影响&#xff0c;我国科技尤其是上游核心技术受制于人的现状对我 国经济发展提出了严峻考验。在全球产业从工业经济向数字经济升级的关键时期&#xff0c;中国明确 “数字中国”建设战略&#xff0c; 抢占数字经济产业链制高点。 在…

Python开发工具PyCharm入门指南 - 用户界面主题更改

JetBrains PyCharm是一种Python IDE&#xff0c;其带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具。此外&#xff0c;该IDE提供了一些高级功能&#xff0c;以用于Django框架下的专业Web开发。 界面主题定义了窗口、对话框、按钮和用户界面的所有可视元素的外观…

vscode开发avalonia

安装 安装.net 8 安装avalonia模板 dotnet new install Avalonia.Templates创建项目 dotnet new avalonia.app -o GetStartedApp安装c# dev kit插件和Avalonia for VSCode Community dotnet run运行 修改代码 MainWindow.axaml <Window xmlns"https://githu…

企业层面经济政策不确定性感知数据(2001-2023年)

1.指标介绍 企业经济政策不确定性感知指的是企业在面对政府经济政策变动时所感受到的风险和不确定性程度&#xff0c;这种感知会影响企业的投资决策、生产计划和市场策略 文章根据上市公司披露的MD&A文本&#xff0c;提取指标衡量企业个体面临的经济政策不确定性。 2.参…

了解线性回归、岭回归和套索回归

逐步对 Linear、Ridge 和 Lasso 回归进行数学理解。 ​ LASSO&#xff08;左&#xff09;和岭回归&#xff08;右&#xff09;的约束区域 一、说明 在本文中&#xff0c;我们将深入探讨机器学习中两种基本正则化技术的基础和应用&#xff1a;Ridge 回归和 Lasso 回归。这些方…

脊髓损伤小伙伴的活力重启秘籍! 让我们一起动起来,拥抱不一样的精彩生活✨

Hey小伙伴们~&#x1f44b; 今天咱们来聊聊一个超级重要又温暖的话题——脊髓损伤后的锻炼大法来啦&#xff01;&#x1f389; 记住&#xff0c;无论遇到什么挑战&#xff0c;我们都要像打不死的小强一样&#xff0c;活力满满地面对每一天&#xff01;&#x1f4aa; 首先&#…

基础进阶-搭建pxe网络安装环境实现服务器自动部署

目录 原理解释 ​编辑 开机界面解释 搭建步骤 下载环境需要用到的基本程序 查看帮助 帮助内容解释 环境搭建 修改 DHCP 修改 default 文件 测试 原理解释 开机界面解释 在开机界面中&#xff0c;圈起来的部分显示的就是光盘&#xff0c;我们需要将光盘转换成网络的 在…

.NET内网实战:模拟Installer关闭Defender

01基本介绍 02编码实现 原理上通过Windows API函数将当前进程的权限提升至TrustedInstaller&#xff0c;从而实现了对Windows Defender服务的控制。通常可以利用Windows API中的OpenSCManager、OpenProcessToken、ImpersonateLoggedOnUser以及ControlService等函数协同工作&am…