【数据结构C/C++】多维数组的原理、访问方式以及作用
文章目录
- 什么是多维数组?
- 代码讲解使用方式
- 为什么指针遍历的方式是这样子的?(助你理解指针的含义)
- 使用场景
- 408考研各数据结构C/C++代码(Continually updating)
什么是多维数组?
在C语言中,多维数组的存储实际上是在内存中按照一维数组的方式连续存储数据的。多维数组的底层原理可以理解为是一维数组的扩展。每个维度的大小(元素个数)决定了存储空间的布局。
考虑一个二维数组的例子,例如int arr[3][4],表示一个3行4列的整数数组。底层存储原理如下:
首先,内存中会分配一个连续的存储空间,大小为3 * 4 * sizeof(int)字节,其中sizeof(int)表示一个整数占用的字节数。
数组的元素在内存中按照行优先(C语言的约定)方式存储,也就是说,首先存储第一行的所有元素,然后是第二行的所有元素,以此类推。
如果我们想访问数组的某个元素,例如arr[1][2],系统会通过内存偏移计算来找到对应的位置。在这个例子中,偏移计算如下:
偏移 = 行号 * 每行的元素个数 + 列号
偏移 = 1 * 4 + 2 = 6
这意味着arr[1][2]的数据存储在偏移地址6的位置上。
多维数组的每个维度的大小(行数和列数等)会影响内存布局和偏移计算。例如,如果有一个三维数组int arr[2][3][4],那么在内存中会按照一维数组的形式存储,同时需要考虑三个维度的大小来计算偏移。
这种按照行优先方式存储多维数组的原理使得访问连续内存位置的元素更加高效,因为它充分利用了现代计算机的缓存机制,可以减少内存访问的开销。同时,它也意味着多维数组的元素在内存中是连续存储的,这对于访问大量数据的性能非常重要。
代码讲解使用方式
#include <stdio.h>int main() {// 定义一个二维数组,表示3行4列的矩阵int matrix[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}};// 使用指针遍历多维数组int *ptr = &matrix[0][0]; // 定义一个指向第一个元素的指针printf("遍历多维数组的元素:\n");for (int i = 0; i < 3; i++) {for (int j = 0; j < 4; j++) {// 使用指针访问当前元素int element = *(ptr + i * 4 + j); // 计算偏移并解引用指针printf("%d ", element); //指针遍历方法printf("%d ", matrix[i][j]); // 数组下标遍历方法}printf("\n");}return 0;
}
原理解释:
-
我们首先定义了一个二维数组 int matrix[3][4],表示一个3行4列的矩阵。
-
然后,我们定义一个指针 int *ptr 并将其初始化为指向数组的第一个元素,也就是 matrix[0][0]。在C语言中,多维数组在内存中是按照一维数组的方式连续存储的,因此我们可以使用指针来遍历多维数组。
-
接下来,我们使用两个嵌套的循环来遍历多维数组的元素。外层循环控制行,内层循环控制列。
-
在循环中,我们使用指针 ptr 来访问当前元素。为了计算当前元素的偏移,我们使用了 i * 4 + j 的方式,其中 i 表示当前行数,j 表示当前列数。这是因为在二维数组中,每行有4个元素。
-
我们通过 *(ptr + i * 4 + j) 来解引用指针,从而获取当前元素的值,并使用 printf 函数打印出来。
为什么指针遍历的方式是这样子的?(助你理解指针的含义)
在Linux64系统下,我们知道一个int类型的大小是4bit。
那么假设我们的数组的第一个元素的起始地址为0x00,那么第一个元素应该是0x04。也就是如下:
matrix[0][0] (地址0) matrix[0][1] (地址4) matrix[0][2] (地址8) matrix[0][3] (地址12)
matrix[1][0] (地址16) matrix[1][1] (地址20) matrix[1][2] (地址24) matrix[1][3] (地址28)
matrix[2][0] (地址32) matrix[2][1] (地址36) matrix[2][2] (地址40) matrix[2][3] (地址44)
但是为什么我们在使用指针遍历的时候,写法是:
int element = *(ptr + i * 4 + j); // 计算偏移并解引用指针
根据这个计算方式,我们在第一行中得到以下偏移:
matrix[0][0] 的偏移是 i * 4 + j = 0 * 4 + 0 = 0。
matrix[0][1] 的偏移是 i * 4 + j = 0 * 4 + 1 = 1。
matrix[0][2] 的偏移是 i * 4 + j = 0 * 4 + 2 = 2。
matrix[0][3] 的偏移是 i * 4 + j = 0 * 4 + 3 = 3。
这看上去与我们上面写的地址是0,4,8不太一样,为什么呢?
这是因为 ptr 是一个指向 int 类型的指针,它的增量是 sizeof(int) 字节,因此每次移动一个 int 的大小(通常是4字节)。这正是为什么我们在计算偏移时只需要考虑 i 和 j,而不需要考虑元素的物理大小。
所以,偏移是按照指针的增量来计算的,而不是根据元素的物理大小。这种方式使得多维数组的遍历更加通用,不受元素大小的影响。
使用场景
多维数组是一种在程序中组织和存储数据的重要数据结构,它可以用于解决各种问题,具有广泛的应用场景。以下是多维数组的一些常见作用和使用场景,以及一些例子:
-
矩阵和二维数据的表示: 多维数组通常用于表示矩阵、表格和类似的二维数据结构。例如,图像处理中的像素矩阵、棋盘游戏的棋盘状态、二维地图等。
-
多维数据的存储和处理: 多维数组可以用于存储和处理具有多个维度的数据。例如,科学和工程领域中的多维数据集,如立体图像数据、声音信号、气象数据等(当然,考研你肯定处理不到这玩意,我写代码可能用得到)。
-
矩阵运算: 线性代数中的矩阵运算和矩阵乘法通常需要使用多维数组表示。例如,计算机图形学中的矩阵变换和投影(算法题经常需要用到矩阵变换)。
嵌套结构: 多维数组可以用于表示嵌套结构的数据,例如多层的树形结构或多层的地理数据。
图和网络算法: 图和网络算法通常使用多维数组来表示节点和边的关系。例如,图的邻接矩阵或邻接列表(图是最经典的用多维数组的方法了)。
游戏开发: 多维数组常用于游戏开发中的地图、迷宫、游戏棋盘、角色位置等(迷宫算法以及路径算法也都会用到)。
动态规划: 动态规划算法中,多维数组常用于存储中间计算结果,以解决优化问题,如最短路径、最长公共子序列等(最常见的还是在动态规划中)。
空间和时间复杂度优化: 多维数组可以用于优化数据访问和算法性能。例如,在一些计算密集型任务中,多维数组的合理使用可以降低时间复杂度。
408考研各数据结构C/C++代码(Continually updating)
408考研各数据结构C/C++代码(Continually updating)
这个模块是我应一些朋友的需求,希望我能开一个专栏,专门提供考研408中各种常用的数据结构的代码,并且希望我附上比较完整的注释以及提供用户输入功能,ok,fine,这个专栏会一直更新,直到我认为没有新的数据结构可以讲解了。
目前我比较熟悉的数据结构如下:
数组、链表、队列、栈、树、B/B+树、红黑树、Hash、图。
所以我会先有空更新出如下几个数据结构的代码,欢迎关注。 当然,在我前两年的博客中,对于链表、哈夫曼树等常用数据结构,我都提供了比较完整的详细的实现以及思路讲解,有兴趣可以去考古。
相关文章:
【数据结构C/C++】多维数组的原理、访问方式以及作用
文章目录 什么是多维数组?代码讲解使用方式为什么指针遍历的方式是这样子的?(助你理解指针的含义)使用场景408考研各数据结构C/C代码(Continually updating) 什么是多维数组? 在C语言中&#x…...
2023年中国烹饪机器人市场发展概况分析:整体规模较小,市场仍处于培育期[图]
烹饪机器人仍属于家用电器范畴,是烹饪小家电的进一步细分,它是烹饪小家电、人工智能和服务机器在厨房领域的融合。烹饪机器人是一种智能化厨房设备,可以根据预设的程序实现自动翻炒和烹饪,是多功能料理机和炒菜机结合的产物。 烹…...
Android原生实现控件选择背景变色方案(API28及以上)
Android控件点击/选择后控件背景变色的实现方式有很多种,例如使用selector的xml文件实现。这里介绍一下另一种Android原生的点击/选择实现方案(API28及以上),也就是ColorStateListDrawable。 ColorStateListDrawable是一个可根据不…...
为什么要学C语言及C语言存在的意义
为什么要学C语言及C语言存在的意义 汇编生C,C生万物。linus说自己最喜欢的语言就是C语言,因为看到写出的代码就能想到对应的汇编码。一方面说明C语言足够简洁,没有像C中一样的复杂概念封装,另一方面也说明C语言足够的底层…...
数据结构——空间复杂度
空间复杂度,与算法运行时所需的内存空间有关。 默认问题规模为n。 举例案例,具体分析。 1.全是普通变量 2.一维数组 3.二维数组 4.递归--变量 不递归的时候空间复杂度是O(1),递归的话递归n次,乘以n,所以空间复杂度…...
uniapp:swiper-demo效果
单元格轮播 <swiper class"swiper1" :circular"true" :autoplay"true" interval"3000" previous-margin"195rpx" next-margin"195rpx"><swiper-item v-for"(item,index) in 5" :key"inde…...
Graphviz 作图工具
选择 Graphviz 作为作图工具,主要是想通过代码创建图标,按照 Graphviz 的代码规范就可以生成 svg 的图片。当然,这样的工具也有很多,有些 markdown 编辑器也做了集成,比如: flowchart.jsMermaid 了解 Gra…...
vue、vuex状态管理、vuex的核心概念state状态
每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同: Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候&…...
【QT】Qt Application Manager启动应用源码分析
Qt Application Manager启动应用源码分析 Qt Application Manager(以下简称QTAM)是QT推出的一款应用管理程序,可以把它简单理解成Android的LauncherSystemUI。但是,QTAM又集成了Wayland功能,并且自身实现了一套Compos…...
MyBatisPlus(十)判空查询
说明 判空查询,对应SQL语句中的 IS NULL语句,查询对应字段为 NULL 的数据。 isNull /*** 查询用户列表, 查询条件:电子邮箱为 null 。*/Testvoid isNull() {LambdaQueryWrapper<User> wrapper new LambdaQueryWrapper<…...
AIGC(生成式AI)试用 8 -- 曾经的难题
长假,远离电脑、远离手机、远离社交。 阴雨连绵,望着窗外发呆,AIGC为何物?有什么问题要问AIGC?AIGC可以代替我来发呆,还是可是为我空出时间发呆? 如果可以替代我发呆,要我何…...
文化主题公园旅游景点3d全景VR交互体验加深了他们对历史文化的认知和印象
如今,沉浸式体验被广泛应用于文旅行业,尤其是在旅游演艺活动中。在许多城市,沉浸式旅游演艺活动已成为游客“必打卡”项目之一。因其独特体验和强互动性,这类演艺活动不仅吸引了外地游客,也吸引了本地观众。 随着信息化…...
京东数据分析平台:2023年8月京东奶粉行业品牌销售排行榜
鲸参谋监测的京东平台8月份奶粉市场销售数据已出炉! 鲸参谋数据显示,8月份京东平台上奶粉的销售量将近700万件,环比增长约15%,同比则下滑约19%;销售额将近23亿元,环比增长约4%,同比则下滑约3%。…...
Java 21:虚拟线程介绍
Java 21 版本更新中最重要的功能之一就是虚拟线程 (JEP 444)。这些轻量级线程减少了编写、维护和观察高吞吐量并发应用程序所需的工作量。 正如我的许多其他文章一样,在推出新功能之前,让我们先看看 Java 21 版本更新前的现状,以便更好地了解…...
Redis-缓存穿透,缓存击穿,缓存雪崩
缓存穿透,缓存击穿,缓存雪崩 缓存穿透处理方案解决方案1 缓存空数据解决方案2 布隆过滤器 缓存击穿处理方案解决方案 1 互斥锁解决方案2 逻辑过期 缓存雪崩处理方案解决方案 1 给不同的key的过期时间设置添加一个随机值,降低同一个时段大量ke…...
如何使用Docker实现分布式Web自动化!
01、前言 顺着docker的发展,很多测试的同学也已经在测试工作上使用docker作为环境基础去进行一些自动化测试,这篇文章主要讲述在docker中使用浏览器进行自动化测试如果可以实现可视化,同时可以对浏览器进行相关的操作。 02、开篇 首先我们…...
从零开始:制作出色的产品原型图的详细教程
在设计产品的初始版本或模型时,产品原型起着非常重要的作用,可以帮助设计师和团队更好地了解产品需求和用户需求,优化和改进设计,确保设计最终满足用户的需求和期望。如果你不知道如何绘制产品原型图,绘制产品原型图的…...
美国访问学者签证如何申请加急办理?
许多中国学者梦想着前往美国深造,积累更多的学术经验和知识。然而,签证申请过程可能会变得复杂和繁琐,特别是如果你需要在紧急情况下前往美国。但别担心,本文知识人网小编将为您介绍美国访问学者签证加急办理的一些建议和步骤。 首…...
33 WEB漏洞-逻辑越权之水平垂直越权全解
目录 前言水平,垂直越权,未授权访问Pikachu-本地水平垂直越权演示(漏洞成因)墨者水平-身份认证失效漏洞实战(漏洞成因)原理越权检测-Burpsuite插件Authz安装测试(插件使用)修复防御方案 前言 越权漏洞文章分享:https://www.cnblogs.com/zhen…...
【FreeRTOS】【STM32】02 FreeRTOS 移植
基于 [野火]《FreeRTOS%20内核实现与应用开发实战—基于STM32》 正点原子《STM32F429FreeRTOS开发手册_V1.2》 准备 基础工程,例如点灯 FreeRTOS 系统源码 FreeRTOS 移植 上一章节已经说明了Free RTOS的源码文件在移植时所需要的,FreeRTOS 为我们提供…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
从零开始了解数据采集(二十八)——制造业数字孪生
近年来,我国的工业领域正经历一场前所未有的数字化变革,从“双碳目标”到工业互联网平台的推广,国家政策和市场需求共同推动了制造业的升级。在这场变革中,数字孪生技术成为备受关注的关键工具,它不仅让企业“看见”设…...
JS红宝书笔记 - 3.3 变量
要定义变量,可以使用var操作符,后跟变量名 ES实现变量初始化,因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符,可以创建一个全局变量 如果需要定义…...
算法—栈系列
一:删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...
Mac flutter环境搭建
一、下载flutter sdk 制作 Android 应用 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 1、查看mac电脑处理器选择sdk 2、解压 unzip ~/Downloads/flutter_macos_arm64_3.32.2-stable.zip \ -d ~/development/ 3、添加环境变量 命令行打开配置环境变量文件 ope…...
