一、基礎定義
演算法定義:
演算法是解決特定問題求解步驟的描述,在計算機中表現為指令的有限序列,並且每條指令表示乙個或多個操作,每乙個操作都有特定的功能
演算法的基本特點:
(1)輸入輸出:演算法具有0個或多個輸入,至少有乙個或多個輸出;
(2)有窮性:指演算法在執行有限的步驟之後,自動結束而不會出現無限迴圈,並且每乙個步驟在可接受的時間內完成;
(3)確定性:演算法的每一步驟都具有確定的含義,不會出現二義性。
(4)可行性:演算法的每一步都必須是可行的,也就是說,每一步都能夠通過執行有限次數完成;
演算法設計要求:
(1)正確性:演算法的正確性是指演算法至少應該具有輸入、輸出和加工處理無歧義性、能正確反映問題的需求、能夠得到問題的正確答案;
(2)可讀性:演算法設計的另一目的是為了便於閱讀、理解和交流
(3)健壯性:當輸入資料不合法時,演算法也能做出相關處理,而不是產生異常或莫名其妙的結果;
(4)時間效率高儲存量低:時間效率指的是演算法的執行時間,對於同乙個問題,如果有多個演算法能夠解決,執行時間短的演算法效率高,執行時間長的效率低。儲存量需求指的是演算法在執行過程中需要的最大儲存空間,主要指演算法程式執行時所占用的記憶體或外部硬碟儲存空間。設計演算法應該盡量滿足時間效率高和儲存量低的需求。
二、演算法效率檢測
演算法的執行效率大都指演算法的執行時間,我們如何衡量乙個演算法程式的執行效率吶,可以通過事後統計和事前估算兩種方式來衡量。
(1)事後統計方法:這種方法主要是通過設計好的測試程式和資料,利用計算機計時器對不同演算法編制的程式的執行時間進行比較,從而確定演算法效率的高低;該種方式有兩個特點,第一:必須要通過設計好的測試程式和資料進行效率檢測,但是通過少量的資料無法很好的判斷演算法的好壞,所以我們需要創造大量的測試資料進行檢驗,對於這個這個資料大量,我們很難進行評估和設計;第二:該種方式需要花費大量的時間和精力去編制好程式,如果最終結果發現這是一套很糟糕的演算法,就前功盡棄;
(2)事前估算方法:在計算機程式編制前,依據統計方法對演算法進行估算,我們可以發現,乙個用高階程式語言編寫的程式在計算機上執行時所消耗的時間取決於下列因素:
1、編譯產生的**質量;
2、演算法採用的策略、方法;
3、問題的輸入規模;
4、機器執行指令的速度;
這其中,1和4 分別由軟體和計算機硬體因素有關,所以我們只能從演算法的策略和輸入規模進行衡量,根據資料的輸入規模和計算方式,我們有以下兩個指標可以估算演算法的執行效率:
時間複雜度:
在進行演算法分析時,語句總的執行次數 t(n)是關於問題規模 n的函式,進而分析 t(n)隨 n 的變化情況並確定 t(n)的數量級。演算法的時間複雜度,也就是演算法的時間量度,記作:t(n)=o(f(n))。它表示隨問題規模 n 的增大,演算法執行時間的增長率和f(n)的增長率相同,稱作演算法的漸近時間複雜度,簡稱為時間複雜度。其中 f(n)是問題規模 n 的某個函式。
計算時間複雜度(大o階)三條法則:
1.用常數 1我們對以下幾類**進行分析:取代執行時間中的所有加法常數。
2.在修改後的執行次數函式中,只保留最高端項。
3.如果最高端項存在且不是 1,則去除與這個項相乘的常數。得到的結果就是大 o 階。
(1)常數階:
int sum = 0,n = 100; /*執行一次*/可以看出演算法的函式執行次數函式為f(n)= 3;按照我們計算大o階的三條法則的第一條,所有常數項使用1來代替,所以該**的時間複雜度為o(1) 而不是o(3); 如果 我們將中間的 sum = (1+n)*n/2; 執行10次,那麼我們的執行次數函式為 f(n)=12,結果依舊是常數,它的時間複雜度依舊為o(1),對於這種分支結構而言,執行次數始終是恆定的,不會隨著n 變化而變化,所以他們的時間複雜度始終未o(1)sum = (1+n)*n/2; /*執行一次*/
printf("%d", sum); /* 執行一次*/
(2)線性階:
for(int i=0; i它的迴圈的時間複雜度為 o(n),因為迴圈體中的**須要執行 n次
(3)對數階:
int count = 1;由於每次count乘以 2 之後,就距離n更近了一分。也就是說,有多少個 2 相乘後大於n,則會退出迴圈。由 2 x =n得到x=log 2 n。所以這個迴圈的時間複雜度為o(logn)while (count < n)
(4)平方階:
for(int i=0; i對於外層的迴圈,不過是內部這個時間複雜度為o(n)的語句,再迴圈n次。所以這段**的時間複雜度為o(n^2)。
注意以下**片段:
int i,j;由於當 i = 0 時,內迴圈執行了 n 次,當 i = 1 時,執行了 n-1 次,……當 i = n-1 時,內迴圈執行了 1 次。所以總的執行次數:for(i = 0; i < n; i++)
}
n+(n-1)+(n-2)+(n-3)..........+1= n^2 /2 +n/2(等差數列求和)
按照我們推斷大o階的第二條和第三條,只保留最高端,並且去掉最高端的常數,最終得到結果為o(n^2);
常用的時間複雜度所耗費的時間從小到大依次是:
o(1)2)3)2^n)
空間複雜度演算法的空間複雜度通過計算演算法所需的儲存空間實現,演算法空間複雜度的計算公式記作:s(n)= o(f(n)),其中,n為問題的規模,f(n)為語句關於n所佔儲存空間的函式。一般情況下,乙個程式在機器上執行時,除了需要儲存程式本身的指令、常數、變數和輸入資料外,還需要儲存對資料操作的儲存單元,若輸入資料所佔空間只取決於問題本身,和演算法無關,這樣只需要分析該演算法在實現時所需的輔助單元即可。若演算法執行時所需的輔助空間相對於輸入資料量而言是個常數,則稱此演算法為原地工作,空間複雜度為0(1)。
通常, 我們都使用"時間複雜度"來指執行時間的需求,使用"空間複雜度"指空間需求。當不用限定詞地使用"複雜度'時,通常都是指時間複雜度。
三、總結
很多夥伴說,現在 cpu 公升級越來越快,根本不用考慮演算法的優劣,實現功能即可,使用者感覺不到演算法好壞造成的快慢,但是做個假設:如果cpu在短短幾年間,速度提高了 100 倍,這其實已經很誇張了。而我們的某個演算法本可以寫出時間複雜度是o(n)的程式,卻寫出了o(n 2 )的程式,僅僅因為容易想到,也容易寫。即在o(n 2 )的時間複雜度演算法程式下,速度其實只提高了 10 倍,而對於o(n) 複雜度的演算法說,那才是真的 100 倍。 也就是說,一台老式cpu的計算機執行o(n)的程式和一台速度提高 100 倍新式cpu執行o(n 2 )的程式。最終效率高的勝利方卻是老式cpu的計算機,原因就在於演算法的優劣直接決定了程式執行的效率,所以演算法的重要性可想而知。
最後附上一張常用排序演算法的效率比較圖:
參考內容:
《大話資料結構》
網頁設計標準尺寸
網頁設計標準尺寸 1 800 600下,網頁寬度保持在778以內,就不會出現水平滾動條,高度則視版面和內容決定。2 1024 768下,網頁寬度保持在1002以內,如果滿框顯示的話,高度是612 615之間.就不會出現水平滾動條和垂直滾動條。3 在ps裡面做網頁可以在800 600狀態下顯示全屏,頁...
網頁設計標準尺寸
800 600下,網頁寬度保持在778以內,就不會出現水平滾動條,高度則視版面和內容決定。2 1024 768下,網頁寬度保持在1002以內,如果滿框顯示的話,高度是612 615之間.就不會出現水平滾動條和垂直滾動條。3 在ps裡面做網頁可以在800 600狀態下顯示全屏,頁面的下方又不會出現滑動...
網頁設計標準尺寸
網頁設計標準尺寸 1 800 600下,網頁寬度保持在778以內,就不會出現水平滾動條,高度則視版面和內容決定。2 1024 768下,網頁寬度保持在1002以內,如果滿框顯示的話,高度是612 615之間。就不會出現水平滾動條和垂直滾動條。3 在ps裡面做網頁可以在800 600狀態下顯示全屏,頁...