【数据结构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 为我们提供…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...