1.概述
1.1定義
一個算法的存儲量包括形參所占空間和臨時變量所占空間。在對算法進行存儲空間分析時,只考察臨時變量所占空間。
算法的空間復雜度定義為:S(n) = O(g(n))
表示隨着問題規模 n 的增大,算法運行所需存儲量的增長率與 g(n) 的增長率相同。
1.2補充
例如,有以下算法,其中臨時空間為變量i、maxi占用的空間。
所以,空間復雜度是對一個算法在運行過程中臨時占用的存儲空間大小的量度,一般也作為問題規模n的函數,以數量級形式給出,記作:
S(n)=O(g(n))、Ω(g(n))或Θ(g(n))
其中漸進符號的含義與時間復雜度中的含義相同。
int max(int a[],int n) { int i,maxi=0; for (i=1;i<=n;i++) if (a[i]>a[maxi]) maxi=i; return a[maxi]; } 函數體內分配的變量空間為臨時空間,不計形參占用的空間, 這里的僅計i、maxi變量的空間,其空間復雜度為O(1)。
注意:若輸入數據所占空間只取決於問題本身,和算法無關,則只需要分析除輸入和程序之外的輔助變量所占額外空間。若所需額外空間相對於輸入數據量來說是常數,則稱此算法為原地工作。若所需存儲量依賴於特定的輸入,則通常按最壞情況考慮。引用相當於給個變量別名,不占用空間。
- 算法的存儲量包括:
- 1.輸入數據所占空間
- 2.程序本身所占空間
- 3.輔助變量所占空間
【例1.9】分析例1.6算法的空間復雜度。 void func(int n) { int i=1,k=100; while (i<=n) { k++; i+=2; } } 解:該算法是一個非遞歸算法,其中只臨時分配了i、k兩個變量的空間,它與問題規模n無關,所以其空間復雜度均為O(1),即該算法為原時工作算法。
【例1.10】有如下遞歸算法,分析調用 maxelem(a,0,n-1) 的空間復雜度。 int maxelem(int a[],int i,int j) { int mid=(i+j)/2,max1,max2; if (i<j) { max1=maxelem(a,i,mid); max2=maxelem(a,mid+1,j); return (max1>max2)?max1:max2; } else return a[i]; }
解:執行該遞歸算法需要多次調用自身,每次調用只臨時分配3個整型變量的空間(O(1))。
設調用maxelem(a,0,n-1)的空間為S(n),有: S(n)=O(1) 當n=1 S(n)=2S(n/2)+O(1) 當n>1 o(1)是int mid=(i+j)/2,max1,max2;常量空間 則: S(n) = 2S(n/2)+1=2[2S(n/22)+1]+1=22S(n/22)+1+21 = 23S(n/23)+1+21+22 = … = 2kS(n/2k)+1+21+22+…+2k-1(設n=2k,即k=log2n) = n*1+2k-1 = 2n-1 = O(n)
1.3注意
為什么算法占用的空間只考慮臨時空間,而不必考慮形參的空間呢?這是因為形參的空間會在調用該算法的算法中考慮,例如,以下maxfun算法調用max算法:
void maxfun() { int b[]={1,2,3,4,5},n=5; printf("Max=%d\n",max(b,n)); }
int max(int a[],int n) { int i,maxi=0; for (i=1;i<=n;i++) if (a[i]>a[maxi]) maxi=i; return a[maxi]; }
maxfun算法中為b數組分配了相應的內存空間,其空間復雜度為O(n),如果在max算法中再考慮形參a的空間,這樣重復計算了占用的空間。