排序算法的時間與空間複雜度分析

時間複雜度

時間複雜度是同一問題可用不同算法解決,而一個算法的質量優劣將影響到算法乃至程序的效率。算法分析的目的在於選擇合適算法和改進算法。

計算機科學中,算法的時間複雜度是一個函數,它定性描述了該算法的運行時間。這是一個關於代表算法輸入值的字符串的長度的函數。時間複雜度常用大O符號表述,不包括這個函數的低階項和首項係數。使用這種方式時,時間複雜度可被稱爲是漸近的,它考察當輸入值大小趨近無窮時的情況。

在我們常用的排序算法中,最常見的5種時間複雜度爲 O\left (log_{2}n \right )O\left (n \right )O\left (nlog_{2}n \right )O\left (n^{2} \right )O\left ( n! \right )

其函數圖像如下:橫座標代表數據量,縱座標代表所需時間

從左到右分別爲O(logn)、O(n)、O(nlogn)、O(n^2)、O(n!)

空間複雜度

空間複雜度(Space Complexity)是對一個算法在運行過程中臨時佔用存儲空間大小的量度,記做S(n)=O(f(n))。比如直接插入排序的時間複雜度是O(n^2),空間複雜度是O(1) 。而一般的遞歸算法就要有O(n)的空間複雜度了,因爲每次遞歸都要存儲返回信息。一個算法的優劣主要從算法的執行時間和所需要佔用的存儲空間兩個方面衡量。 

一個算法的空間複雜度只考慮在運行過程中爲局部變量分配的存儲空間的大小,它包括爲參數表中形參變量分配的存儲空間和爲在函數體中定義的局部變量分配的存儲空間兩個部分。

若一個算法爲 遞歸算法,其空間複雜度爲遞歸所使用的堆棧空間的大小,它等於一次調用所分配的臨時存儲空間的大小乘以被調用的次數(即爲遞歸調用的次數加1,這個1表示開始進行的一次非遞歸調用)。

算法的空間複雜度一般也以數量級的形式給出。如當一個算法的空間複雜度爲一個常量,即不隨被處理數據量n的大小而改變時,可表示爲O(1);

當一個算法的空間複雜度與以2爲底的n的對數成正比時,可表示爲O(log2n);

當一個算法的空間複雜度與n成線性比例關係時,可表示爲O(n)。

 

每種排序的時間與空間複雜度

類別 排序方法 時間複雜度 空間複雜度 穩定性
平均情況 最好情況 最壞情況 輔助存儲
插入排序 直接插入 O\left ( n^{2} \right ) O\left ( n \right ) O\left ( n^{2} \right ) O(1) 穩定
希爾排序 O\left ( n^{1.3} \right ) O\left ( n \right ) O\left ( n^{2} \right ) O(1) 不穩定
選擇排序 直接選擇 O\left ( n^{2} \right ) O\left ( n^{2} \right ) O\left ( n^{2} \right ) O(1) 不穩定
堆排序 O\left (nlog_{2}n \right ) O\left (nlog_{2}n \right ) O\left (nlog_{2}n \right ) O(1) 不穩定
交換排序 冒泡排序 O\left ( n^{2} \right ) O\left ( n \right ) O\left ( n^{2} \right ) O(1) 穩定
快速排序 O\left (nlog_{2}n \right ) O\left (nlog_{2}n \right ) O\left ( n^{2} \right ) O\left (nlog_{2}n \right ) 不穩定
歸併排序 O\left (nlog_{2}n \right ) O\left (nlog_{2}n \right ) O\left (nlog_{2}n \right ) O\left ( n \right ) 穩定

 

對快速排序進行復雜度分析:

以下內容摘自算法圖解

快速排序的性能高度依賴於你選擇的基準值。假設你總是將第一個元素用作基準值,且要處理的數組是有序的。由於快速排序算法不檢查輸入數組是否有序,因此它依然嘗試對其進行排序。

注意,數組並沒有被分成兩半,相反,其中一個子數組始終爲空,這導致調用棧非常長。現在假設你總是將中間的元素用作基準值,在這種情況下,調用棧如下。

調用棧短得多!因爲你每次都將數組分成兩半,所以不需要那麼多遞歸調用。你很快就到達了基線條件,因此調用棧短得多。

第一個示例展示的是最糟情況,而第二個示例展示的是最佳情況。在最糟情況下,棧長爲O\left ( n^{2} \right ),而在最佳情況下,棧長爲O\left (log_{2}n \right )

現在來看看棧的第一層。你將一個元素用作基準值,並將其他的元素劃分到兩個子數組中。這涉及數組中的全部8個元素,因此該操作的時間爲O\left ( n \right )。在調用棧的第一層,涉及全部8個元素,但實際上,在調用棧的每層都涉及O\left ( n \right )個元素。

即便以不同的方式劃分數組,每次也將涉及O\left ( n \right )個元素。

因此,完成每層所需的時間都爲O\left ( n \right )

在這個示例中,層數爲O\left (log_{2}n \right )(用技術術語說,調用棧的高度爲O\left (log_{2}n \right )),而每層需要的時間爲O\left ( n \right )。因此整個算法需要的時間爲O\left ( n \right ) * O\left (log_{2}n \right ) = O\left (nlog_{2}n \right )。這就是最佳情況。
在最糟情況下,有O\left ( n \right )層,因此該算法的運行時間爲O\left ( n \right ) * O\left ( n \right ) = O\left (n^{2} \right )

這裏要告訴你的是,最佳情況也是平均情況。只要你每次都隨機地選擇一個數組元素作爲基準值,快速排序的平均運行時間就將爲O\left (nlog_{2}n \right )

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章