【数据结构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 为我们提供…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
[特殊字符] 手撸 Redis 互斥锁那些坑
📖 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作,想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁,也顺便跟 Redisson 的 RLock 机制对比了下,记录一波,别踩我踩过…...
