数据结构与算法 (2)复杂度---(空间复杂度)

这是复杂度的第二篇讲解,空间复杂度


在这里插入图片描述
今天我们将进入空间复杂度的学习,也会举一些例子,方便大家理解

空间复杂度

定义

空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度,注意,他是一个量度,纠结具体占用了多少个字节,这是没有意义的,所以在这里我们采用的也是大O渐进表示法。

还有一点需要注意的是:函数运行时会创建栈帧(就像函数的形参,临时变量以及寄存器信息,都是存在栈帧中的),会占用一些空间,但是这些空间是不算在空间复杂度中的,而且他也是一个常量。
举几个例子:

例一(常数级)

void func(int* a,int* b)      
{      
  int c = *a;    
  *a = *b;    
  *b = c;    
}

就像上面这一串代码,他的时间复杂度就是O(1),因为它申请的额外空间就只有c一个,是常数级的,这样的就是O(1)

例二(动态申请内存)

int* fun2(int n)  
{  
  int *a = (int *)malloc(sizeof(n)*n);  
  return a;                                                                       
} 

再比如说这个例子,你申请的空间和n有关,设n的值为N 你的空间复杂度就是O(N),实际上O里面这个不一定非要是N,任意一个字母都可以,但是看N比较顺眼,大家用的也多。
这是显示申请内存的例子,下面我们说一说递归。

递归求空间复杂度

关于递归算法的空间复杂度也有一个公式,就是:单次运行需要空间*递归的深度,这个也很好理解,因为递归是一层一层的,假如我们算法本来要申请的空间是N,那么深度每增加一层,需要的空间也是需要提升的(栈帧是常量),我们举个例子:

在这里插入图片描述
这个求递归的阶乘我们之前在学习时间复杂度的时候用过,这里再套用一下。
像这样,我们的递归每深入一次,就会创建一个栈帧,这个栈帧不会立马销毁,而是占用着我们的内存,只有递归到头返回的时候,才会逐步销毁。并且栈帧的大小是编译的时候就已经规定好的,是一个常量,这个时候我们就可以把他当作1来处理,那这个阶乘递归的空间复杂度就是O(N),和我们要求谁的阶乘有关。
下面我们再来看看斐波那契数列的空间复杂度:
在这里插入图片描述
代码就是这样,我们主要看他的深度是怎么样的:
在这里插入图片描述
像这样fib(5)在运行的时候会创建一个栈帧 然后继续深入是fib(4),fib(3),fib(2)
到fib(2)时它可以返回了,他的栈帧就会被销毁,返回到fib(3),可是 fib(3)还要继续求fib(1),这时就会给fib(1)再创建一个栈帧,而这个栈帧就恰好和fib(3)的栈帧深度相同:
在这里插入图片描述
大概就是这样,然后我们发现fib(3)可以返回了,并且销毁了他的栈帧,返回之后fib(4)还要求 fib(2),又创建了栈帧,这时我们发现,递归的深度不会比刚才fib(2)创建的栈帧更深了,显然,这就是斐波那契数列递归算法的深度,由于栈帧是一个常量,而且在函数中我们没有申请其他的空间,所以斐波那契数列的空间复杂度就是 1*(N-1),简化之后就是O(N)。

总结

以上就是对空间复杂度的介绍,实际上不用死记硬背太多,我们遇到了不会算的就画图,深入思考一下就可以了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值