2024年5月9号

 接着昨天的学习任务,我们开始学习

3. 空间复杂度

的概念和相关内容

运行这个算法所占用的物理空间?标记为S(n)

同样的为了估算“内存空间占用情况”,和时间复杂度一样,这个领域的开拓者设定了一个用“问题的输入规模n”来表示一个函数,并且这个函数会体现一些相对应的概念,用于衡量与估计占用内存空间的情况。

有些我们已经学习过了,可以复用的知识点积木(就像乐高那样的一些基本可以复用最小基本单元积木一样),我们可以继续在这里复用,我们需要尽快快速的积累更多的积木,让我们的地基面更广,也更扎实。

这里的一个最小基本单元知识点积木是渐进符号:

在「2. 时间复杂度」中提到的渐进符号,也同样适用于空间复杂度的度量。

空间复杂度的函数可以表示为S(n)=O(f(n))

它表示的是随着问题规模 n的增大,算法所占空间的增长趋势(斜率)跟 f(n)相同。

所以我们提出的空间复杂度的概念,本质上核心目的是为了通过辅助空间来衡量,评估、估算

算法的内存空间占用情况。

什么是算法的辅助空间?

相比于算法的时间复杂度计算来说,算法的空间复杂度更容易计算,主要包括「局部变量(算法范围内定义的变量)所占用的存储空间」和「系统为实现递归(如果算法是递归的话)所使用的堆栈空间」两个部分。

两种重要概念来了

局部变量:

局部变量是在算法范围内定义的变量,它们的作用范围仅限于当前函数或代码块。在计算空间复杂度时,我们通常需要考虑局部变量所占用的存储空间。这包括了变量的存储大小以及变量的数量。通常,局部变量的存储空间在算法执行过程中是固定的,并且与输入规模无关。

PS:

但是这个算法范围内定义的变量中,算法范围内怎么理解呢

"算法范围内定义的变量"指的是在算法执行过程中创建的变量,其作用范围仅限于当前算法的执行过程中。这些变量通常是在函数或代码块内部声明的,并且它们的生命周期仅限于函数或代码块的执行期间。

具体来说,当我们定义一个函数时,在函数内部声明的变量就属于局部变量,它们的作用范围仅限于函数的执行过程中。例如:

python

Copy code

def my_function(): x = 10 # 这是一个局部变量,作用范围仅限于my_function函数的执行过程中

# 其他代码...

在这个例子中,变量x被称为局部变量,因为它是在函数my_function内部声明的,其作用范围仅限于函数my_function的执行过程中。

另外,如果在代码块内部(如循环、条件语句等)声明的变量也被视为局部变量,其作用范围仅限于该代码块的执行过程中。例如:

python

for i in range(5): y = i # 这是一个局部变量,作用范围仅限于循环代码块的执行过程中

# 其他代码...

总之,算法范围内定义的变量即为在算法执行过程中创建的局部变量,其作用范围仅限于当前算法的执行过程中,超出该范围后,这些变量将被销毁。

这块如果你不感兴趣可以跳过:

如果你想了解的更细致一点,你可以问

问:局部变量存储在内存的哪个空间呢?

答案:

局部变量通常存储在内存的栈区中。

栈区是用于存储函数调用的局部变量、参数和返回地址等信息的内存区域。每当函数被调用时,系统会为该函数在栈区分配一段内存空间,称为栈帧(stack frame)。栈帧中包含了函数的局部变量、参数值、函数返回地址等信息。当函数执行完成并返回时,对应的栈帧会被销毁,释放其所占用的内存空间。

因此,局部变量的生命周期通常与函数的执行过程相对应,它们在函数执行期间存在,并且随着函数的退出而被销毁。这种栈区的管理方式使得函数调用可以高效地进行,同时也限制了局部变量的生命周期和作用范围。

几个重要的概念

两个内存空间或者内存区域

"栈区"和"堆栈空间"是两个不同的概念。

  1. 栈区(Stack):栈区是内存中的一部分,用于存储函数调用的局部变量、参数和返回地址等信息。在程序执行过程中,每当函数被调用时,系统会为该函数分配一个栈帧(stack frame),栈帧中包含了函数的局部变量、参数值、函数返回地址等信息。栈区遵循后进先出(LIFO)的原则,即最后进入栈的数据最先被取出。栈区的管理由操作系统自动完成,通常情况下是连续的内存空间,栈的大小在程序运行时是固定的。

  2. 堆栈空间(Heap):堆栈空间通常是指存储在堆区中的动态分配的内存空间。堆区是用于动态分配内存的内存区域,程序员可以通过调用特定的内存分配函数(如mallocnew等)来分配内存,再通过调用相应的释放函数(如freedelete等)来释放内存。堆区的内存分配和释放由程序员显式地控制,可以在运行时动态地分配和释放内存。与栈区不同,堆区的内存大小在程序运行时是可变的。

因此,栈区和堆栈空间是两个不同的概念,它们分别用于不同的目的,并且在内存中有着不同的管理方式和特点。

根据上述我再展开讲讲

栈区(stack)为内存中的一个特定的内存空间。在计算机内存中,栈区是用于存储函数调用的局部变量、参数和返回地址等信息的内存区域,是栈数据结构的一部分。栈区遵循后进先出(LIFO)的原则,即最后进入栈的数据最先被取出。栈区的内存分配和释放由操作系统自动管理,其大小通常是固定的。

 栈区(Stack):栈区是内存中的一部分,用于存储函数调用的局部变量、参数和返回地址等信息。在程序执行过程中,每当函数被调用时,系统会为该函数分配一个栈帧(stack frame),栈帧中包含了函数的局部变量、参数值、函数返回地址等信息。栈区遵循后进先出(LIFO)的原则,即最后进入栈的数据最先被取出。栈区的管理由操作系统自动完成,通常情况下是连续的内存空间,栈的大小在程序运行时是固定的。

PS:

"栈帧"(stack frame)和"栈区"(stack)的区别:栈数据结构中的两个相关但不同的概念。

  1. 栈帧(stack frame):栈帧是指在函数调用过程中,为每个函数在栈上分配的一段内存空间,用于存储函数的局部变量、参数值、函数返回地址等信息。每当函数被调用时,系统会为该函数分配一个新的栈帧,并将其推入栈的顶部(栈顶)。当函数执行完成并返回时,相应的栈帧会被弹出栈,释放其所占用的内存空间。栈帧的创建和销毁是函数调用的基本机制之一,它使得函数调用可以高效地进行,并且限制了局部变量的作用范围和生命周期。

  2. 栈区(stack):栈区是指存储栈帧的内存区域,用于存储函数调用过程中的局部变量、参数和返回地址等信息。栈区遵循后进先出(LIFO)的原则,即最后进入栈的数据最先被取出。栈区的大小通常在程序运行时是固定的,并且由操作系统自动管理。栈区的特点包括快速分配和释放、空间利用率高等。

因此,栈帧是栈区中的一个特定数据结构,用于存储函数调用的相关信息。而栈区则是存储栈帧的内存区域,是函数调用过程中内存管理的重要组成部分。

堆栈空间通常是指存储在堆区(Heap)中的动态分配的内存空间。堆区是程序运行时用于动态分配内存的一部分,程序员可以通过调用特定的内存分配函数(如mallocnew等)来向堆区申请内存空间。堆区的内存分配和释放由程序员显式地控制,可以在运行时动态地分配和释放内存。因此,堆栈空间通常指的是在堆区中动态分配的内存空间,其大小和生命周期由程序员决定。

结论

为了计算空间复杂度或者估算“内存空间占用情况”

1:先判断算法是否涉及递归,如果不涉及递归进入下一步

2:如果涉及递归,计算递归的big O

3:如果不涉及递归,则计算在算法范围内定义的变量的数量(这些变量它们的作用范围仅限于当前函数或代码块)。

4:计算基本语句执行次数的数量级:只需要计算基本语句执行次数的数量级,即保证函数中的最高次幂正确即可。像最高次幂的系数和低次幂可以忽略。
5:用大 O 表示法表示时间复杂度:将上一步中计算的数量级放入 O 渐进上界符号中。(大家请注意,这一步看似简单,但是在我理解big O的时候,我认为它至少表达了两次含义1:增长趋势是一样的,用数学世界的语言描述就是斜率是一样的,图像上他们是平行的两个曲线,分别一个在上,一个在下;2:用时间来描述时间复杂度的T的增长是不会超过这个bigO的,因为bigO是它的上界,但是不管是时间T还是bigO,用数学语言描述,他们都是自变量为n的函数,图像上他们是平行的两个曲线,分别一个在上,一个在下,在上面的就是bigO含糊描述的曲线,下面的就是T函数描述的曲线)

————————————————

  • 20
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值