3.空间复杂度
空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度。
空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟实践复杂度类似,也使用大O渐进表示法。
注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。
我们直接上例题来讲解
void lystyle(int* a, int n)
{
assert(a);
for (size_t end = n; end > 0; --end)
{
int exchange = 0;
for (size_t i = 1; i < end; i++)
{
if (a[i - 1] > a[i])
{
swap(&a[i - 1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
}
首先我们要思考一下void lystyle(int*a;int n)这个函数声明中创建的a和n算不算到空间复杂度里面去,显然是不用的
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度。(计算的是函数额外创建的变量个数)
这整个函数里面一共创建了三个变量分别是exchange,i,n占用的内存是不同的
因此创建变量是常数个,O(1)这个地方不知道为啥是O(1)可以看上一期的暑期数据结构 时间复杂度-CSDN博客
我们接下来看一个很有意思的事
但是为啥会导致这样呢?
原因在于我们使用函数时会开辟一片空间,函数结束时会将那片空间还给系统 ,但是下次另一个函数使用时开辟的那个空间还是原来函数的
那么还是上一期的函数(时间复杂度我会放到每日一题以一个数学专业的学生去讲解)
long long Fib(int N)
{
if (N <= 3)
return 1;
return Fib(N - 1) + Fib(N - 2);
}
那么这个地方的空间复杂度是多少呢?
有人可能说是O(0)但是只有函数本身声明中的变量才不算入空间复杂度里面,但是递归产生的变量会被算到时间复杂度里面
那么还有人可能说和时间复杂度一样是O(N*N),因为我每递归一次就执行了一次语句
但是结果也不对
那么答案是多少呢?
答案是O(N)
这个地方递归执行是有顺序的
这个地方return Fib(N - 1) + Fib(N - 2);
要先计算Fib(N - 1)再计算Fib(N - 2);
要计算Fib(N - 1)就要先算Fib(N - 2)+Fib(N -3 )
递归是一步一步实现的,不遇到return 不停止我们以N=6来画一个计算的过程图
这个地方我们看箭头4和5,我们先执行函数Fib(3)使用完之后函数空间还给系统,但是执行Fib(4)本质上再开辟的那个空间还是和Fib(3)一样的
因此这个地方同一深度的函数的是同一片空间(深度从上到下看)
因此这个地方的空间复杂度就是O(N)(我么只看最左侧看它最深度有多深就行)