介紹
在學習具體的數據結構和算法之前,每一位初學者都要掌握一個技能,即善于運用時間複雜度和空間複雜度來衡量一個算法的運行效率。類似于時間複雜度的讨論,一個算法的空間複雜度(SpaceComplexity)S(n)定義為該算法所耗費的存儲空間,它也是問題規模n的函數。漸近空間複雜度也常常簡稱為空間複雜度。空間複雜度(SpaceComplexity)是對一個算法在運行過程中臨時占用存儲空間大小的量度。
一個算法在計算機存儲器上所占用的存儲空間,包括存儲算法本身所占用的存儲空間,算法的輸入輸出數據所占用的存儲空間和算法在運行過程中臨時占用的存儲空間這三個方面。算法的輸入輸出數據所占用的存儲空間是由要解決的問題決定的,是通過參數表由調用函數傳遞而來的,它不随本算法的不同而改變。
存儲算法本身所占用的存儲空間與算法書寫的長短成正比,要壓縮這方面的存儲空間,就必須編寫出較短的算法。算法在運行過程中臨時占用的存儲空間随算法的不同而異,有的算法隻需要占用少量的臨時工作單元,而且不随問題規模的大小而改變,我們稱這種算法是“就地"進行的,是節省存儲的算法,如這一節介紹過的幾個算法都是如此;有的算法需要占用的臨時工作單元數與解決問題的規模n有關,它随着n的增大而增大,當n較大時,将占用較多的存儲單元,例如将在第九章介紹的快速排序和歸并排序算法就屬于這種情況。
分析一個算法所占用的存儲空間要從各方面綜合考慮。如對于遞歸算法來說,一般都比較簡短,算法本身所占用的存儲空間較少,但運行時需要一個附加堆棧,從而占用較多的臨時工作單元;若寫成非遞歸算法,一般可能比較長,算法本身占用的存儲空間較多,但運行時将可能需要較少的存儲單元。
一個算法的空間複雜度隻考慮在運行過程中為局部變量分配的存儲空間的大小,它包括為參數表中形參變量分配的存儲空間和為在函數體中定義的局部變量分配的存儲空間兩個部分。
若一個算法為遞歸算法,其空間複雜度為遞歸所使用的堆棧空間的大小,它等于一次調用所分配的臨時存儲空間的大小乘以被調用的次數(即為遞歸調用的次數加1,這個1表示開始進行的一次非遞歸調用)。
算法的空間複雜度一般也以數量級的形式給出。如當一個算法的空間複雜度為一個常量,即不随被處理數據量n的大小而改變時,可表示為O(1);當一個算法的空間複雜度與以2為底的n的對數成正比時,可表示為O(log2n);當一個算法的空間複雜度與n成線性比例關系時,可表示為O(n).若形參為數組,則隻需要為它分配一個存儲由實參傳送來的一個地址指針的空間,即一個機器字長空間;若形參為引用方式,則也隻需要為其分配存儲一個地址的空間,用它來存儲對應實參變量的地址,以便由系統自動引用實參變量。
時間與空間複雜度比較
對于一個算法,其時間複雜度和空間複雜度往往是相互影響的。當追求一個較好的時間複雜度時,可能會使空間複雜度的性能變差,即可能導緻占用較多的存儲空間;反之,當追求一個較好的空間複雜度時,可能會使時間複雜度的性能變差,即可能導緻占用較長的運行時間。
另外,算法的所有性能之間都存在着或多或少的相互影響。因此,當設計一個算法(特别是大型算法)時,要綜合考慮算法的各項性能,算法的使用頻率,算法處理的數據量的大小,算法描述語言的特性,算法運行的機器系統環境等各方面因素,才能夠設計出比較好的算法。算法的時間複雜度和空間複雜度合稱為算法的複雜度。