一、算法:
算法是對特定問題求解步驟的一種描述,是獨立存在的一種解決問題的方法和思想。它是指令的有限序列,其中每一條指令表示一個或多個操作;
此外,成為一個算法需要滿足以下條件或特性:
(1)有窮性。一個算法必須總是在執行有窮步之后結束,且每一步都可在有窮時間內完成。
(2)確定性。算法中每一條指令必須有確切的含義讀者理解時不會產生二義性。並且,在任何條件下,算法只有唯一的一條執行路徑,即對於相同的輸入只能得出相同的輸出。
(3)可行性。一個算法是能行的,即算法中描述的操作都是可以通過已經實現的基本運算執行有限次來實現的。
(4)輸入。零個或多個的輸入。
(5)輸出。一個或多個的輸出。
二、算法設計的要求
通常設計一個“好”的算法應考慮達到以下目標:
(1)正確性。對於合法輸入能夠得到滿足的結果;算法能夠處理非法處理,並得到合理結果;算法對於邊界數據和壓力數據都能得到滿足的結果。
(2)可讀性。算法要方便閱讀,理解和交流,只有自己能看得懂,其它人都看不懂,談和好算法。
(3)健壯性。算法不應該產生莫名其妙的結果,一會兒正確,一會兒又是其它結果。
(4)高性價比,效率與低存儲量需求。利用最少的時間和資源得到滿足要求的結果,可以通過(時間復雜度和空間復雜度來判定)
同一問題可用不同算法解決,而一個算法的質量優劣將影響到算法乃至程序的效率。算法分析的目的在於選擇合適算法和改進算法。
計算機科學中,算法的時間復雜度是一個函數,它定量描述了該算法的運行時間。這是一個關於代表算法輸入值的字符串的長度的函數。時間復雜度常用大O符號【O】表述,不包括這個函數的低階項和首項系數。使用這種方式時,時間復雜度可被稱為是漸近的,它考察當輸入值大小趨近無窮時的情況。
算法復雜度分為時間復雜度和空間復雜度。其作用:時間復雜度是指執行算法所需要的計算工作量;而空間復雜度是指執行這個算法所需要的內存空間。(算法的復雜性體現在運行該算法時的計算機所需資源的多少上,計算機資源最重要的是時間和空間(即寄存器)資源,因此復雜度分為時間和空間復雜度)。
1、時間復雜度
(1)時間頻度
一個算法執行所耗費的時間,從理論上是不能算出來的,必須上機運行測試才能知道。但我們不可能也沒有必要對每個算法都上機測試,只需知道哪個算法花費的時間多,哪個算法花費的時間少就可以了。並且一個算法花費的時間與算法中語句的執行次數成正比例,哪個算法中語句執行次數多,它花費時間就多。一個算法中的語句執行次數稱為語句頻度或時間頻度。記為T(n)。(算法中的基本操作一般指算法中最深層循環內的語句)
(2)時間復雜度
在剛才提到的時間頻度中,n稱為問題的規模,當n不斷變化時,時間頻度T(n)也會不斷變化。但有時我們想知道它變化時呈現什么規律。為此,我們引入時間復雜度的概念。
一般情況下,算法中基本操作重復執行的次數是問題規模n的某個函數,用T(n)表示,若有某個輔助函數f(n), 使得當n趨近於無窮大時,T(n)/f(n)的極限值為不等於零的常數,則稱f(n)是T(n)的同數量級函數。記作T(n)=O(f(n)), 稱O(f(n))為算法的漸進時間復雜度 ,簡稱時間復雜度。O是數量級的符號。
在各種不同算法中,若算法中語句執行次數為一個常數,則時間復雜度為O(1)。另外,在時間頻度不相同時,時間復雜度有可能相同,如T(n)=n2+3n+4與T(n)=4n2+2n+1它們的頻度不同,但時間復雜度相同,都為O(n2)。
(3)最壞時間復雜度和平均時間復雜度
最壞情況下的時間復雜度稱最壞時間復雜度。一般不特別說明,討論的時間復雜度均是最壞情況下的時間復雜度。 這樣做的原因是:最壞情況下的時間復雜度是算法在任何輸入實例上運行時間的上界,分析最壞的情況以估算算法指向時間的一個上界。這就保證了算法的運行時間不會比任何更長。
在最壞情況下的時間復雜度為T(n)=0(n),它表示對於任何輸入實例,該算法的運行時間不可能大於0(n)。 平均時間復雜度是指所有可能的輸入實例均以等概率出現的情況下,算法的期望運行時間。
指數階0(2n),顯然,時間復雜度為指數階0(2n)的算法效率極低,當n值稍大時就無法應用。
按數量級遞增排列,常見的時間復雜度有:
| 常數階 | 對數階 | 線性階 | 線性對數階 | 平方階 | 立方階 | …… | K次方階 | 指數階 |
| O(1) | O(log2 n ) | O(n) | O(nlog2 n) | O(n2 ) | O(n3 ) | O(nk ) | O(2n ) |
復雜度低 ---->---->---->---->---->---->---->---->---->---->---->---->----> 復雜度高
隨着問題規模n的不斷增大,上述時間復雜度不斷增大,算法的執行效率越低。
時間復雜度的分析方法:
1、時間復雜度就是函數中基本操作所執行的次數
2、一般默認的是最壞時間復雜度,即分析最壞情況下所能執行的次數
3、忽略掉常數項
4、關注運行時間的增長趨勢,關注函數式中增長最快的表達式,忽略系數
5、計算時間復雜度是估算隨着n的增長函數執行次數的增長趨勢
6、遞歸算法的時間復雜度為:遞歸總次數 * 每次遞歸中基本操作所執行的次數
計算方法
1.一般情況下,算法中基本操作重復執行的次數是問題規模n的某個函數,用T(n)表示,若有某個輔助函數f(n),使得當n趨近於無窮大時,T(n)/f(n)的極限值為不等於零的常數,則稱f(n)是T(n)的同數量級函數。記作T(n)=O(f(n)),稱O(f(n)) 為算法的漸進時間復雜度,簡稱時間復雜度。
分析:隨着模塊n的增大,算法執行的時間的增長率和 f(n) 的增長率成正比,所以 f(n) 越小,算法的時間復雜度越低,算法的效率越高。
2. 在計算時間復雜度的時候,先找出算法的基本操作,然后根據相應的各語句確定它的執行次數,再找出 T(n) 的同數量級(它的同數量級有以下:1,log2n,n,n log2n ,n的平方,n的三次方,2的n次方,n!),找出后,f(n) = 該數量級,若 T(n)/f(n) 求極限可得到一常數c,則時間復雜度T(n) = O(f(n))
則有 T(n) = n 的平方+n的三次方,根據上面括號里的同數量級,我們可以確定 n的三次方 為T(n)的同數量級
則有 f(n) = n的三次方,然后根據 T(n)/f(n) 求極限可得到常數c
則該算法的時間復雜度:T(n) = O(n^3) 注:n^3即是n的3次方。
3.時間復雜度比較簡單的計算方法是:看看有幾重for循環,只有一重則時間復雜度為O(n),二重則為O(n^2),依此類推,如果有二分則為O(logn),二分例如快速冪、二分查找,如果一個for循環套一個二分,那么時間復雜度則為O(nlogn)。
空間復雜度:
算法的空間復雜度並不是計算實際占用的空間,而是計算整個算法的輔助空間單元的個數,與問題的規模沒有關系。算法的空間復雜度S(n)定義為該算法所耗費空間的數量級。
S(n)=O(f(n)) 若算法執行時所需要的輔助空間相對於輸入數據量n而言是一個常數,則稱這個算法的輔助空間為O(1);
遞歸算法的空間復雜度:遞歸深度N*每次遞歸所要的輔助空間, 如果每次遞歸所需的輔助空間是常數,則遞歸的空間復雜度是 O(N).
空間復雜度的分析方法:
一個算法的空間復雜度S(n)定義為該算法所耗費的存儲空間,它也是問題規模n的函數。空間復雜度是對一個算法在運行過程中臨時占用存儲空間大小的量度。
一個算法在計算機存儲器上所占用的存儲空間,包括存儲算法本身所占用的存儲空間,算法的輸入輸出數據所占用的存儲空間和算法在運行過程中臨時占用的存儲空間這三個方面。
一個算法的空間復雜度只考慮在運行過程中為局部變量分配的存儲空間的大小,它包括為參數表中形參變量分配的存儲空間和為在函數體中定義的局部變量分配的存儲空間兩個部分。
算法的空間復雜度一般也以數量級的形式給出。如當一個算法的空間復雜度為一個常量,即不隨被處理數據量n的大小而改變時,可表示為O(1);當一個算法的空間復雜度與以2為底的n的對數成正比時,可表示為O(log2n);當一個算法的空間復雜度與n成線性比例關系時,可表示為O(n)。若形參為數組,則只需要為它分配一個存儲由實參傳送來的一個地址指針的空間,即一個機器字長空間;若形參為引用方式,則也只需要為其分配存儲一個地址的空間,用它來存儲對應實參變量的地址,以便由系統自動引用實參變量。
空間復雜度補充
一個程序的空間復雜度是指運行完一個程序所需內存的大小。利用程序的空間復雜度,可以對程序的運行所需要的內存多少有個預先估計。一個程序執行時除了需要存儲空間和存儲本身所使用的指令、常數、變量和輸入數據外,還需要一些對數據進行操作的工作單元和存儲一些為現實計算所需信息的輔助空間。程序執行時所需存儲空間包括以下兩部分。
(1)固定部分。這部分空間的大小與輸入/輸出的數據的個數多少、數值無關。主要包括指令空間(即代碼空間)、數據空間(常量、簡單變量)等所占的空間。這部分屬於靜態空間。
(2)可變空間,這部分空間的主要包括動態分配的空間,以及遞歸棧所需的空間等。這部分的空間大小與算法有關。
一個算法所需的存儲空間用f(n)表示。S(n)=O(f(n)) 其中n為問題的規模,S(n)表示空間復雜度。
時間與空間復雜度比較
對於一個算法,其時間復雜度和空間復雜度往往是相互影響的。當追求一個較好的時間復雜度時,可能會使空間復雜度的性能變差,即可能導致占用較多的存儲空間;反之,當追求一個較好的空間復雜度時,可能會使時間復雜度的性能變差,即可能導致占用較長的運行時間。
另外,算法的所有性能之間都存在着或多或少的相互影響。因此,當設計一個算法(特別是大型算法)時,要綜合考慮算法的各項性能,算法的使用頻率,算法處理的數據量的大小,算法描述語言的特性,算法運行的機器系統環境等各方面因素,才能夠設計出比較好的算法。算法的時間復雜度和空間復雜度合稱為算法的復雜度。
常用的算法的時間復雜度和空間復雜度:
| 排序法 | 平均時間 | 最差情形 | 穩定度 | 額外空間 | 備注 |
| 冒泡 | O(n2 ) | O(n2 ) | 穩定 | O(1) | n較小時較好 |
| 交換 | O(n2 ) | O(n2 ) | 不穩定 | O(1) | n較小時較好 |
| 選擇 | O(n2 ) | O(n2 ) | 不穩定 | O(1) | n較小時較好 |
| 插入 | O(n2 ) | O(n2 ) | 穩定 | O(1) | 大部分已排序時較好 |
| 基數 | O(logR B) | O(logR B) | 穩定 | O(n) | B是真數(0-9), R是基數(個十百) |
| Shell | O(nlogn) | O(ns ) 1<s<2 | 不穩定 | O(1) | s是所選分組 |
| 快速 | O(nlogn) | O(n2 ) | 不穩定 | O(nlogn) | n較大時較好 |
| 歸並 | O(nlogn) | O(nlogn) | 穩定 | O(1) | n較大時較好 |
| 堆 | O(nlogn) | O(nlogn) | 不穩定 | O(1) | n較大時較好
|
穩定的排序:保證,排序關鍵字相同的情況下,對象的相對位置不變

