算法預備軍(2)~算法的一些概念

說明:算法預備軍系列內容均爲個人的學習筆記,主要是指數據結構方面的,後面在繼續學習的過程中會陸續分享相關內容.數據結構這塊主要學習來源爲<大話數據結構這本書>,大家不喜歡摘錄的,可以自行看書.

算法:算法是解決特定問題求解步驟的描述,在計算機中表現爲指令的有限序列,並且每條指令表示一個或多個操作。
算法定義中,提到了指令,指令能被人或機器等計算裝置執行。它可以是計算機指令,也可以是我們平時的語言文字。爲了解決某個或某類問題,需要把指令表示成一定的操作序列,操作序列包括一組操作,每一個操作都完成特定的功能,這就是算法了。

算法具有五個基本特性:輸入,輸出,有窮性,確定性和可行性。

輸入與輸出:算法具有零個或多個輸入,算法至少有一個或多個輸出,算法是一定需要輸出的。
有窮性:指算法在執行有限的步驟之後,自動結束而不會出現無限循環,並且每一個步驟在可接受的時間內完成。
確定性:算法的每一步驟都具有確定的含義,不會出現二義性。算法在一定條件下,只有一條執行路徑,相同的輸入只能有唯一的輸出結果。算法的每個步驟被精確定義而無歧義。
可行性:算法的每一步都必須是可行的,也就是說,每一步都能夠通過執行有限次數完成。

算法設計的要求:
1.正確性:算法的正確性是指算法至少應該具有輸入,輸出和加工處理無歧義性,能正確反映問題的需求,能夠得到問題的正確答案。
但是算法的“正確”通常在用法上有很大的區別,大體分爲以下四個層次:
(1)算法程序沒有語法錯誤
(2)算法程序對於合法的輸入數據能夠產生滿足要求的輸出結果
(3)算法程序對於非法的輸入數據能夠得出滿足規格說明的結果
(4)算法程序對於精心選擇的,甚至刁難的測試數據都有滿足要求的輸出結果
算法的正確性在大部分情況下都不可能用程序來證明,而是用數學方法證明的。證明一個複雜算法在所有層次上都是正確的,代價非常昂貴。所以一般情況下,我們把層次3作爲一個算法是否正確的標準。
2.可讀性:算法設計的另一目的是爲了便於閱讀,理解和交流。可讀性是算法(也包括實現它的代碼)
好壞很重要的標誌。
3.健壯性:當輸入數據不合法時,算法也能夠做出相關處理,而不是產生異常或莫名其妙的結果。一個好的算法還應該能對輸入數據不合法的情況做合適的處理。
4.時間效率高和存儲量低:好的算法還應該具備時間效率高和存儲量低的特點。設計算法應該儘量滿足時間效率高和存儲量低的要求。
好的算法,應該具有正確性,可讀性,健壯性,高效率和低存儲量的特徵。

算法效率的度量方法:(1)事後統計方法(2)事前分析估算方法

事後統計方法:這種方法主要是通過設計好的測試程序和數據,利用計算機計時器對不同算法編制的程序的運行時間進行比較,從而確定算法效率的高低。但此種方法缺陷太多。
事前分析估算方法:在計算機程序編制前,依據統計方法對算法進行估算。
經過分析,我們發現,一個用高級程序語言編寫的程序在計算機上運行時所消耗的時間取決於下列因素:
(1)算法採用的策略、方法
(2)編譯產生的代碼質量
(3)問題的輸入規模
(4)機器執行指令的速度

一個程序的運行時間,依賴於算法的好壞和問題的輸入規模
測定運行時間最可靠的方法就是計算對運行時間有消耗的基本操作的執行次數。最終,在分析程序的運行時間時。最重要的是把程序看成是獨立於程序設計語言的算法或一系列步驟。
我們在分析一個算法的運行時間時,重要的是把基本操作的數量與輸入規模關聯起來,即基本操作的數量必須表示成輸入規模的函數。

函數的漸近增長
函數漸近增長:輸入規模n在沒有限制的情況下,只要超過一個數值N,這個函數就總是大於另一個函數,我們稱函數是漸近增長的。
函數的漸近增長:給定兩個函數f(n)和g(n),如果存在一個整數N,使得對於所有的n>N,f(n)總是比g(n)大,那麼,我們說f(n)的增長漸近快於g(n)

判斷一個算法的效率時,函數中的常數和其他次要項常常可以忽略,而更應該關注主項(最高階項)的階數
某個算法,隨着n的增大,它會越來越優於另一算法,或者越來越差於另一算法。這其實就是事前估算方法的理論依據,通過算法時間複雜度來估算算法時間效率。


算法時間複雜度:

算法時間複雜度定義:在進行算法分析時,語句總的執行次數T(n)是關於問題規模n的函數,進而分析T(n)隨n的變化情況並確定T(n)的數量級。算法的時間複雜度,也就是算法的時間量度。記作:T(n)=O(f(n))。它表示隨問題規模n的增大,算法執行時間的增長率和f(n)的增長率相同,稱作算法的漸近時間複雜度,簡稱爲時間複雜度。其中f(n)是問題規模n的某個函數。
這樣用大寫0()來體現算法時間複雜度的記法,我們稱之爲大O記法。
一般情況下,隨着n的增大,T(n)增長最慢的算法爲最優算法。
O(1)叫常數階、O(n)叫線性階、O(n^2)叫平方階

推導大O階方法
推導大O階:
(1)用常數1取代運行時間中的所有加法常數
(2)在修改後的運行次數函數中,只保留最高階項
(3)如果最高階項存在且不是1,則去除與這個項相乘的常數
得到的結果就是大O階
線性階:線性階的循環結構會複雜很多。要確定某個算法的階次。我們常常需要確定某個特定語句或某個語句集運行的次數。因此,我們要分析算法的複雜度,關鍵就是要分析循環結構的運行情況。

常見的時間複雜度:
O(1)——>常數階
O(n)——>線性階
O(n^2)——>平方階
O(logn)——>對數階
O(nlogn)——>nlogn階
O(n^3)——>立方階
O(2^n)——>指數階

常用的時間複雜度所耗費的時間從小到大依次是:
O(1)<O(n)<O(n^2)<O(logn)<O(nlogn)<O(n^3)<O(2^n)


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