[数据结构](2)空间复杂度详解

接上一篇[数据结构](1)时间复杂度详解_CegghnnoR的博客-CSDN博客

接下来学习空间复杂度。

文章目录

  • 什么是空间复杂度
    • 例1:冒泡排序
    • 例2:斐波那契(非递归)
  • 递归的空间复杂度计算
    • 例1:阶乘
    • 例2:斐波那契(递归)
    • 例3:二分查找

什么是空间复杂度

空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度,记做 S ( n ) = O ( f ( n ) ) S(n)=O(f(n)) S(n)=O(f(n))

首先,空间复杂度不是程序本身(可执行程序文件)的大小,而是程序运行时占用内存空间的大小

空间复杂度的计算与时间复杂度类似,也使用大O渐进表示法

空间复杂度的计算相对来说比较简单,下面直接上例子:

例1:冒泡排序

void bubble(int* arr, int sz) {
	int i, j, tmp;
	for (i = 0; i < sz - 1; i++) {
		for (j = 0; j < sz - 1 - i; j++) {
			if (arr[j] > arr[j + 1]) {
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

不算arr数组的空间,因为它不是我们这个算法开辟出来的。

那么这个算法的空间复杂度为 O ( 1 ) O(1) O(1),因为只开辟常数个额外空间,它所开辟的空间并不会随arr大小的变化而变化。

例2:斐波那契(非递归)

long long* Fibonacci(size_t n) {
	if (n == 0)
		return NULL;
	long long* fibArray = (long long*)malloc((n + 1) * sizeof(long long));
	fibArray[0] = 0;
	fibArray[1] = 1;
	for (int i = 2; i <= n; ++i) {
		fibArray[i] = fibArray[i - 1] + fibArray[i - 2];
	}
	return fibArray;
}

计算斐波那契数列的前n项,并存入一个数组里,

n的增大,fibArray空间也会随之增大,呈线性关系,所以空间复杂度为 O ( n ) O(n) O(n)


递归的空间复杂度计算

递归的空间复杂度 = 递归的深度 * 每次递归的空间复杂度

注意和时间复杂度的计算不同,这里是深度而不是次数。因为时间不可以重复利用,而空间可以。

具体请看例子:

例1:阶乘

long long Fac(size_t N) {
	if (N == 0)
		return 1;
	return Fac(N - 1) * N;
}

递归求阶乘。

每次递归都会开辟1个栈帧压到调用栈里,栈的原理就是先进后出,后进先出。最大深度就是栈的深度。

算法递归调用了N次,开辟了N个栈帧,每个栈帧使用常数个空间,空间复杂度为 O ( n ) O(n) O(n)

例2:斐波那契(递归)

int Fib(int N) {
	if (N < 3)
		return 1;
	return Fib(N - 1) + Fib(N - 2);
}

递归计算斐波那契数列。

按照程序运行顺序,依次将f(5)f(4)f(3)f(2)压入栈中,然后f(2)弹出,f(1)又会补上,f(1)f(3)弹出,f(2)进入 ⋯ ⋯ \cdots\cdots

[数据结构](2)空间复杂度详解_第1张图片

最大深度为5。求第n位的话,最大深度就是n。每次递归的占用常数个空间

所以空间复杂度为 O ( n ) O(n) O(n)

例3:二分查找

上一篇分析了二分查找的时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn),那是非递归版本的,空间复杂度应是 O ( 1 ) O(1) O(1)

那么其递归实现的空间复杂度是多少呢?

int binarySearch(int arr[], int l, int r, int x) {
    if (r >= l) {
        int mid = l + (r - l) / 2;
        if (arr[mid] == x)
            return mid;
        if (arr[mid] > x)
            return binarySearch(arr, l, mid - 1, x);
        return binarySearch(arr, mid + 1, r, x);
    }
    return -1;
}

每次递归占用常数个空间。注意这里传的是数组的地址,每次递归不会创建新的数组。

二分查找的执行次数是 x = log ⁡ 2 n x=\log_2n x=log2n,和这里的递归深度一样。

所以空间复杂度为 O ( log ⁡ n ) O(\log n) O(logn)


算法性能分析到此结束,可以说还是比较全面的,把各种经典例子分析了一遍,希望能有更深刻的理解。

如果对你有帮助的话,希望能多多支持,三连一下~

你可能感兴趣的:(数据结构,数据结构,排序算法,算法,c语言,c++)