算法是解決特定問題求解步驟的描述,在計算機中表現爲指令的有限序列,而且每條指令表示一個或多個操做。算法
算法是須要單獨講解的,在數據結構中談到算法,是爲了幫助理解好數據結構,並不會詳談算法的方方面面。數據結構
1+2+3+.....+100函數
算法1:測試
#include <stdio.h> int main(void) { int i, sum = 0, n = 100; for(i = 1; i <= n; i++){ sum += i; } printf("%d", sum); return 0; }
算法2(高斯的算法):設計
#include <stdio.h> int main(void) { int i, sum = 0, n = 100; sum = (1+n)*n/2; printf("%d", sum); return 0; }
顯然高斯的算法厲害不少。blog
五個基本特性:輸入、輸出、有窮性、肯定性和可行性排序
一、輸入輸出數學
算法具備林哥或多個輸入,但至少有一個或多個輸出,輸出的形式能夠是打印、返回一個或多個值。io
二、有窮性table
算法在指定郵箱的步驟以後,自動結束而不會出現無限循環,且每一個步驟在可接受的時間內完成。
三、肯定性
算法的每一步驟都具備肯定的含義,不會出現二義性。
四、可行性
算法的每一步都必須是可行的。
好的算法應該具備:正確性、可讀性、健壯性、高效率和低存儲量的特徵。
一、正確性
至少應該具備輸入、輸出和加工處理無歧義性、能正確反映問題的要求,能獲得問題的正確答案。
但一般對「正確」的理解有很大差異,大體分爲如下四個層次:
(1)沒有語法錯誤;
(2)合法的輸入數據能產生知足要求的輸出結果
(3)非法的輸入數據能知足規格說明的結果;
(4)精心選擇的,甚至刁難的測試數據都有知足要求的輸出結果
證實一個複雜算在全部層次是正確的,代價很是昂貴,因此通常,咱們把層次3做爲一個算法是否正確的標準。
二、可讀性
便於閱讀、理解和交流。可讀性是算法好壞很重要的標誌。
三、健壯性
輸入數據不合法是,算法也能作出相關處理,而不是產生異常或莫名其妙的問題。
四、時間效率高和存儲量低
判斷一個算法的效率時,函數中的參數和其餘次要項經常能夠忽略,而更應該關注主項(最高階項)的階數。
某個算法,隨着n的增加,它會愈來愈優於另外一算法,或愈來愈差於另外一算法。
一、定義
T(n)=O(f(n)) ,表示隨問題規模n的增大,算法執行時間的增加率和f(n)的增加率相同,稱爲算法的漸進時間複雜度,簡稱時間複雜度。其中f(n)是問題規模n的某個函數。
用O( )體現算法時間複雜度的記法,稱爲 大O記法。
二、推導大O階方法
(1)用常數1取代運行時間中的全部加法常數。
(2)在修改後的運行次數函數中,只保留最高階項。
(3)若是最高階項存在且不是1,這去除與這個項相乘的常數。
獲得的結果就是大O階。
三、常數階
下面這個算法不是O(3),而是O(1)
int i, sum = 0, n = 100; /*執行一次*/ sum = (1+n)*n/2; /*執行一次*/ printf("%d", sum); /*執行一次*/
執行時間恆定的算法,稱之爲具備O(1)的時間複雜度,又叫常數階
無論常數是多少,咱們都記做O(1),而不能是O(3)等其餘任何數字,這是初學者常犯的錯誤。
對於分支結構(不包含在循環結構中),不管真假,執行次數都是恆定的,因此其時間複雜度也是O(1).
四、線性階
分析算法的複雜度,關鍵是要分析出循環結構的運行狀況。
下面這段代碼是O(n),由於循環體要執行n次
int i, sum = 0, n = 100; for(i = 1; i <= n; i++){ sum += i; }
五、對數階
下面這段代碼,x = ㏒₂n,因此時間複雜度爲O(㏒n)
int count = 1, n = 100; while (count < n) { count *= 2; }
六、平方階
下面這段代碼,循環體的嵌套,時間複雜度爲O(n²)
for(int i = 0;i <n; i++){ for(int j = 0;j <n; j++){ printf("test") } }
理解大O推導不難,難的是對數列的一些相關運算,這更多的是考察你的數學知識和能力。
時間複雜度耗費時間從小到大排序依次是
執行次數函數 | 階 | 非正式術語 |
12 | O(1) | 常數階 |
5㏒₂n+20 | O(㏒n) | 對數階 |
2n+1 | O(n) | 線性階 |
2n+3n㏒₂n+19 | O(n㏒n) | n㏒n階 |
3n²+2n+1 | O(n²) | 平方階 |
6n³+2n²+3n+4 | O(n³) |
立方階 |
2ⁿ | O(2ⁿ) | 指數階 |
固然還有O(n!)和O(nⁿ),但O(n³)、O(2ⁿ)、O(n!)和O(nⁿ)除非很小的n值,不然哪怕n只是100,都是噩夢般的運行時間,對於這種不切實際的算法時間複雜度,通常都不討論它。
最壞狀況運行時間是一種保證,那就是運行時間將不會再壞了。在應用中,這是一種最重要的需求,一般,咱們提到的運行時間都是最壞狀況的運行時間。
而平均運行時間是全部狀況中最有意義的,由於它是指望的運行時間。
寫代碼時,徹底能夠用空間換取時間。
算法的空間複雜度經過計算算法所需的存儲空間實現,算法空間複雜度的計算公式記做:S(n)=O(f(n))。
咱們討論的通常都是算法的時間複雜度。