在本系列第1篇《走下神坛吧!算法》中提到了:计算复杂度分为时间复杂度与空间复杂度,第3篇《KO!大O——时间复杂度》详细介绍了时间复杂度,本篇文章来讲讲空间复杂度。
空间复杂度和硬件资源开销是一回事情吗?
CPU资源开销分析:
CPU的资源的设计初衷更多的是用于提升计算性能;
对CPU资源的利用,基本原则都是“多多(占用、发挥)益善;
加之CPU的资源空间大小与内存、外存和外设比较,非常有限。
内存资源开销分析:
静态视角:程序要装进内存才能运行
动态视角:程序在运行时,动态申请内存
外存资源开销分析:
静态视角:程序本身,以二进制可执行映像形态,存放在外存上的大小
动态视角:程序在运行时,对外存的需求大小(比如,在进行大数据处理时,将中间结果暂存到外存,腾出内存空间来做计算)
发明DMA、GPU的初衷是分担CPU工作量,提升计算机系统的整体性能。
计算与存储是计算机系统的两大功用,空间复杂度体现存储指标。
不同算法实现的程序的二进制可执行映像的大小,只要不是太烂,通常来说,不会有量级上的差别。
综上所述,我们可以得到如下两个结论:
-
空间复杂度聚焦内存与外存的开销
-
空间复杂度聚焦动态视角
特别地,研究内存的开销,就要了解内存模型:
进一步分解,就是以下三个方面:
程序运行时,静态内存分配量(静态区)
程序运行时,动态内存分配量(堆栈、堆)
程序运行时,外存需求量
静态内存分配
这部分内存分配是用于全局变量和常量的,识别出这些变量类型,并计算出对应的大小,也就得到了该部分内存分配的需求量。具体的方法就是在源代码中找到这些变量声明、定义的地方,然后根据类型来计算大小。
动态内存分配
对于堆:对应动态分配“原语”,如 new
方法、malloc
函数等。
对于堆栈:局部变量对应这一部分,其大小呼应这部分的内存分配大小。
程序运行时的外存需求
要搞清楚程序运行时对外存的需求,首先要找到对外存的访问。
对于高级语言而言,外存是被操作系统抽象成文件来被访问的。所以找到了文件访问的“原语”,也就定位到了对外存的访问。
“文件写原语”: 如writeFile()
等。作用是把内存中装载的数据放到文件中去,对文件大小的占用就反映了对外存的需求量。
“文件读原语”:如readFile()
等。作用是把外存文件中的内容放到内存中去。所涉及的内容大小就反映了对外存的需求量。
从上面的分析可以看出:外存的需求量取决于访问的文件内容大小,后者又和涉及的内存大小相关。所以可以用所涉及的内存大小来表征对外存的需求量。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。