新手刷题对内存结构与形象理解的冲突困惑(持续更新)

97 阅读4分钟

最近开始刷数据结构与算法题, 刷到数组的题感觉很难受很别扭, 体现在解决功能性问题的时候, 我总是太过于聚焦内存细节, 可能是因为我前段时间刚学习了一些变量内存的知识, 让我认识到了一个自己原先很模糊的地方, 导致我现在过度聚焦内存细节, 导致形象化逻辑被干扰, 现在刷题寸步难行, 我透了.

一. 认识问题

我本应优先通过 "形象化模型" (如二维数组 = 矩阵、对象 = 带属性和行为的个体、引用变量 = 指向实体的指针) 理解代码要实现的功能,但却不自觉地陷入"内存分块、栈堆存储、引用存地址"的底层细节中.

比如看到二维数组,脑子里先浮现"引用变量存数组地址, 内层数组由数组的每个元素(也是引用变量)存储", 而非 "矩阵的行与列",导致精力被分散,无法聚焦 "如何遍历、如何计算" 等核心解题逻辑,进而感到 "崩溃、迷茫".

二. 为什么我会产生这种问题?

原因一:

在于我没有明确区分 "刷题时的理解需求" 和 "理解语言特性时的需求"

  • 刷题需要的是 "高效的逻辑映射" (比如把引用变量直接看作 "指向形象化实体的指针", 不用管他在堆还是栈中)
  • 理解 "为什么会出现空指针、为什么修改一个变量会影响另一个" 才需要严谨的内存映射 (比如引用变量存地址、对象在堆里)

这种优先级的混淆,让我在该 "简化思考" 的时候强行 "复杂拆解",导致思考效率低下、逻辑混乱.

原因二:

对于基本数据类型和引用数据类型的变量本质缺乏从形象到底层的过渡认知, 导致一些数据结构在处理时理解断层.

总而言之, 脑子里没有将这些底层内存中的操作熟练的形象化.

三. 解决方案(持续更新)

一个自己能接受的内存模型是刷题时的 "思维基础建设"—— 它不需要和真实内存100%一致,但必须和现实内存没有冲突, 并且能帮你快速预判代码行为、设计操作逻辑.

要解决刷算法题时底层内存导致的混乱, 我们需要在脑内建立起一套形象的内存模型, 目前我抽象出的内存模型要先解决之前碰到的内存中变量的形象化理解问题.

1. 变量的理解

变量和属性都是一块内存地址, 他们相当于给内存地址起了个名, 根据这个名字我们可以找到并使用这块内存中的值, 基本数据类型就是直接获得它里面的值, 引用数据类型就是通过里面存的地址来找到对应的对象.

我们刷题时的理解为: 基本数据类型就是一个值, 引用数据类型就是一个指针

绘图2.jpg

脑内模型.jpg

像是a[3]这种也代表了一块内存的, 其就相当于一个变量, 可以通过它调用内存里面的值或其指向的对象. 总之能代表一块内存的, 就和变量一个用法.

2. 做算法题中我们怎么思考堆中数据结构和变量的关系

首先我们要明确, Java中所有的数据结构(不包括单个数值), 都是存储在堆内存中的, 我们要操作这些数据结构就需要通过通过栈帧中的变量来指向它, 来调用它. 在不同栈帧中有不同局部变量, 我认为做算法题中, 在脑内最方便的思考方式如下.

假设我们在一个Java程序执行中会出现如下的堆栈情况:

整体内存情况.jpg

堆中有三个数据结构, 我们每个栈中都有局部变量指向它们.

当程序在栈1中执行的时候, 我们这时脑子里只想着用栈1中的变量来操作数据结构, 这时脑子里想操作的时候就不用想什么堆内存栈内存了, 直接从数据结构图入手, 脑子里只要知道当前栈帧中有什么变量就行了, 比如位于栈1中时, 我们脑子里操作数据结构的时候就应该有下图:

处于栈1中时.jpg

位于栈2中时, 我们脑子里进行数据结构操作的时候就应该有下图:

处于栈2中时.jpg