算法入門

最近在研究算法,發現其實算法也並不是特別難,只要抓住算法的核心思想,再靜下心來,都 可以自己實現的。在計算機領域,有一些常見的而且又經常使用的算法,這些算法我們應該掌握,比如常見的排序算法;還有一些算法就是特定領域中經常使用的算 法了,這些算法我們只有必須使用時再去學習使用就行了,比如圖像處理中的快速傅里葉變換算法。

算法定義

讓我們來看看算法的定義吧。(以下定義摘自中文維基百科)

在數學和計算機科學/算學之中,算法/演算法/算則法(Algorithm)爲一個計算的具體步驟,常用於計算、數據處理和自動推理。精確而言,算法是一個表示爲有限長列表的有效方法。算法應包含清晰定義的指令用於計算函數。

算法中的指令描述的是一個計算,當其運行時能從一個初始狀態和初始輸入(可能爲空)開始,經過一系列有限而清晰定義的狀態最終產生輸出並停止於一個終態。一個狀態到另一個狀態的轉移不一定是確定的。隨機化算法在內的一些算法,包含了一些隨機輸入。

形式化算法的概念部分源自嘗試解決希爾伯特提出的判定問題,並在其後嘗試定義有效計算性或者有效方法中成形。這些嘗試包括庫爾特·哥德爾、雅 克·埃爾布朗和斯蒂芬·科爾·克萊尼分別於1930年、1934年和1935年提出的遞歸函數,阿隆佐·邱奇於1936年提出的λ演算,1936年 Emil Leon Post的Formulation 1和艾倫·圖靈1937年提出的圖靈機。即使在當前,依然常有直覺想法難以定義爲形式化算法的情況。

算法的特徵

以下是高德納在他的著作《計算機程序設計藝術》裏對算法的特徵歸納:

  • 輸入:一個算法必須有零個或以上輸入量。

  • 輸出:一個算法應有一個或以上輸出量,輸出量是算法計算的結果。

  • 明確性:算法的描述必須無歧義,以保證算法的實際執行結果是精確地匹配要求或期望,通常要求實際運行結果是確定的。

  • 有限性:依據圖靈的定義,一個算法是能夠被任何圖靈完備系統模擬的一串運算,而圖靈機只有有限個狀態、有限個輸入符號和有限個轉移函數(指令)。而一些定義更規定算法必須在有限個步驟內完成任務。

  • 有效性:又稱可行性。能夠實現,算法中描述的操作都是可以通過已經實現的基本運算執行有限次來實現。

算法的基本要素

算法的核心是創建問題抽象的模型和明確求解目標,之後可以根據具體的問題選擇不同的模式和方法完成算法的設計。

說起到算法,那麼怎樣衡量一個算法的好壞呢?答案是通過兩方面來考慮,一是從時間上來考慮,也就是所謂的時間複雜度; 還有就是從空間上來考慮,也就是空間複雜度

時間複雜度

  • 算法的時間複雜度是指算法需要消耗的時間資源。

一般來說,計算機算法是問題規模n 的函數f(n),算法的時間複雜度也因此記做T(n)=O(f(n))

算法執行時間的增長率與f(n) 的增長率正相關,稱作漸近時間複雜度(Asymptotic Time Complexity),簡稱時間複雜度。

常見的時間複雜度有:常數階O(1),對數階O(log2n),線性階O(n), 線性對數階O(nlog2n),平方階O(n2),立方階O(n3),…, k次方階O(nk),指數階O(2n)。隨着問題規模n的不斷增大,上述時間複雜度不斷增大,算法的執行效率越低。

空間複雜度

  • 算法的空間複雜度是指算法需要消耗的空間資源。

其計算和表示方法與時間複雜度類似,一般都用複雜度的漸近性來表示。同時間複雜度相比,空間複雜度的分析要簡單得多。

注意,如果你特別在意算法的時間,在條件允許的情況下可以考慮犧牲空間,也就是所謂的拿空間換取時間。

算法設計的方法

另外,對於算法的設計,通常有以下幾種方法。

  • 窮舉法

  • 分治法

  • 動態規劃法

  • 貪婪算法

  • 線性規劃法

這些方法在此就不深入講解了,因爲每一個都可以單獨拿出長長的一大篇文章來講解,不過,我後面會繼續深入普及這方面的知識的。

算法實現的方法

除了瞭解到算法的常見設計方法,那麼還有哪些常見的實現方法呢。

  • 一般方法

  • 遞歸方法

  • 迭代方法

好了講了這麼多理論,還是用一個例子來解釋下算法到底是什麼。

求最大公約算法

問題:

求兩個自然數的最大公約數 設兩個變量M和N

解題步驟:

1.如果M < N,則交換M和N
2.M被N除,得到餘數R
3.判斷R=0,正確則N即爲“最大公約數”,否則下一步
4.將N賦值給M,將R賦值給N,重做第一步。

代碼實現

void swapi(int *x, int *y)
{    int tmp = *x;    *x = *y;    *y = tmp;
}int gcd(int m, int n)
{    int r;    do {        if (m < n)
            swapi(&m, &n);
        r = m % n;        m = n;
        n = r;
    } while (r);    return m;
}12345678910111213141516171819

好了就講這麼多了,如果有什麼問題可以在下面評論或者發私信給我。

參考文章

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