深圳幻海软件技术有限公司 欢迎您!

数据结构-算法的空间复杂度(1.2)

2023-03-14

目录1.空间复杂度1.1例子1.2空间的特殊性质写在最后:1.空间复杂度空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度。他也是用大O渐进表示法。1.1例子例1:冒泡排序:voidBubbleSort(int*a,intn){assert(a);for(size_te

目录

1.空间复杂度

1.1 例子

1.2 空间的特殊性质

写在最后:


1.空间复杂度

空间复杂度也是一个数学表达式,

是对一个算法在运行过程中临时占用存储空间大小的量度。

他也是用大O渐进表示法。

1.1 例子

例1:

冒泡排序:

  1. void BubbleSort(int* a, int n)
  2. {
  3. assert(a);
  4. for (size_t end = n; end > 0; --end)
  5. {
  6. int exchange = 0;
  7. for (size_t i = 1; i < end; ++i)
  8. {
  9. if (a[i - 1] > a[i])
  10. {
  11. Swap(&a[i - 1], &a[i]);
  12. exchange = 1;
  13. }
  14. }
  15. if (exchange == 0)
  16. break;
  17. }
  18. }

这个是开辟了常数个的空间,

(创建变量就是开辟空间)

它创建了几个变量,所以是开辟了常数个的空间,

所以他的空间复杂度是O(1)。

例2:

斐波那契数列:

  1. long long* Fibonacci(size_t n)
  2. {
  3. if (n == 0)
  4. return NULL;
  5. long long* fibArray = (long long*)malloc((n + 1) * sizeof(long long));
  6. fibArray[0] = 0;
  7. fibArray[1] = 1;
  8. for (int i = 2; i <= n; ++i)
  9. {
  10. fibArray[i] = fibArray[i - 1] + fibArray[i - 2];
  11. }
  12. return fibArray;
  13. }

这里用malloc开辟了n个以上的空间,

所以它的空间复杂度是O(N)。

例3:

阶乘递归:

  1. long long Fac(size_t N)
  2. {
  3. if (N == 0)
  4. return 1;
  5. return Fac(N - 1) * N;
  6. }

这段代码,

因为函数递归,建立函数栈帧,

而函数栈帧里有常数个(空间)变量开辟,

而这段代码,建立了N+1个函数栈帧,

所以它的空间复杂度是O(N)。

1.2 空间的特殊性质

例4:

  1. long long Fib(int N)
  2. {
  3. if (N < 3)
  4. return 1;
  5. return Fib(N - 1) + Fib(N - 2);
  6. }

这段代码的时间复杂度是O(2的N次方)。

但是,它的空间复杂度呢?

实际上,他的空间复杂度是O(N),而不是O(2的N次方)。

为什么呢?

因为函数递归的过程中会建立栈帧,而这段代码在进行递归的时候,

并不会一直递归到最后才返回,

当它递归到一定程度是,会有函数提前返回,

导致栈帧销毁,当新的栈帧建立的时候,

空间就会被重复使用,

例:

  1. #include <stdio.h>
  2. void f1()
  3. {
  4. int b = 0;
  5. printf("%p\n", &b);
  6. }
  7. void f2()
  8. {
  9. int a = 0;
  10. printf("%p\n", &a);
  11. }
  12. int main()
  13. {
  14. f1();
  15. f2();
  16. return 0;
  17. }

输出:

 我们发现,当f1函数的栈帧销毁后,

f2函数栈帧建立,创建的变量地址与f1中创建的变量地址相同,

这就是空间重复利用的特性。

例:

  1. #include <stdio.h>
  2. void f1()
  3. {
  4. int b = 0;
  5. printf("%p\n", &b);
  6. }
  7. void f2()
  8. {
  9. int a = 0;
  10. printf("%p\n", &a);
  11. f1();
  12. }
  13. int main()
  14. {
  15. f2();
  16. return 0;
  17. }

输出:

 当f1函数的栈帧没有销毁,

f2函数的变量自然用不了f1函数的空间,

所以他们的地址当然不同了。

写在最后:

以上就是本篇文章的内容了,感谢你的阅读。

如果喜欢本文的话,欢迎点赞和评论,写下你的见解。

如果想和我一起学习编程,不妨点个关注,我们一起学习,一同成长。

之后我还会输出更多高质量内容,欢迎收看。

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览40346 人正在系统学习中