1. 程式人生 > >程式設計師應該知道的10大基礎演算法

程式設計師應該知道的10大基礎演算法

    計算機演算法是在計算機上有限步內求解某一問題所使用的一組定義明確的規則或對解題步驟的精確描述,通俗點說,就是計算機解題的過程,即以一步接一步的方式詳細描述計算機如何將輸入轉化為所要求的輸出的過程,下面簡稱其為演算法。在這個過程中,無論是形成解題公式還是編寫程式,都是實施某種演算法,前者利用推理實現演算法,後者通過計算機操作實現演算法。

數學技術之演算法概論篇

    計算機演算法的基本特徵可概括為:

    ①  正確性:對於任意一組輸入,包括合理的輸入與不合理的輸入,總能得到預期的輸出;如果一個演算法只是對合理的輸入才能得到預期的輸出,而在異常情況下卻無法預料輸出的結果,那它就是不正確的;

    ②  確切性:演算法的每一步必須有確切的定義,無二義性;

    ③  可行性:演算法是由一系列具體步驟組成的,每一步都能夠準確執行,有確定的執行順序;

    ④  有窮性:演算法必須保證經有限步執行之後結束,即演算法的步驟必須是有限的。在任何情況下,演算法都不能陷入無限迴圈中;

    ⑤  輸  入:演算法有一個或多個輸入,表示運算物件的初始條件;

    ⑥  輸  出:演算法有一個或多個輸出,反映運算的最終結果。

    描述演算法的方法有多種,常用的有自然語言、結構化流程圖、虛擬碼和PAD圖(Problem Analysis Diagram)等,其中最普遍的是流程圖。雖然演算法與計算機程式密切相關,但二者還是不同的,計算機程式是演算法的一個例項,是將演算法通過某種計算機語言表達出來的具體形式;同一個演算法可以用不同的計算機語言來表達。

    對同一個計算問題,不同人會用選用不同的演算法,而不同的演算法使得計算機的執行效率、解題精度和對計算資源的需求會有一定的差異。在實際問題中遇到的高難度計算問題,有的問題在巨型計算機上用普通演算法求解可能要用數天時間,甚至也難以找到可用的解,但用一個好的演算法,即使在普通的微機上,只用幾分鐘就可以找到滿意的解。因此,用計算機求解一個實際問題的計算速度和結果滿意度不僅僅與計算機裝置的水平有關,更取決於求解該問題演算法水平的高低和對問題的適應性,由此可見演算法的重要性。演算法研究的重點隨問題的不同而異,主要有演算法設計和分析、計算複雜性和新的高效演算法設計與研究等。

    對一個給定問題的演算法要進行設計和分析。演算法設計,就是對一個給定問題設計出良好的演算法,並研究設計演算法的規律及其有關的方法;演算法分析,就是對一個給定問題設計出來的演算法,利用數學工具,研究該演算法對問題的適應性和演算法的穩定性、收斂性、複雜性和誤差問題等。

    評價演算法優劣的標準有:

    ①時間複雜度:同樣的問題規模需花費多少時間;

    ②空間複雜度:同樣的問題規模需花費多少空間(主要是記憶體);

    以上兩點越小越好

    ③穩定性:不會因為輸入稍有不同而導致計算結果不穩定的情況發生;

    ④演算法思路是否簡單:越簡單越容易實現越好,最好有現成軟體系統可用。

    演算法複雜度是對演算法在計算機上執行時所需要的計算機資源的度量,需要的時間資源量(如計算所需的步數或反覆執行指令的條數)稱作時間複雜度,需要的空間資源量(即需佔用儲存空間的大小)稱作空間複雜度,是對演算法效率的度量和評價演算法優劣的重要依據。這些量應該集中反映演算法中所採用方法的效率,而從執行該演算法的實際計算機中抽象出來。換句話說,這些量應只依賴於演算法要解的問題的規模、演算法的輸入、輸出和演算法本身。

    計算機和數學技術的快速發展,近些年來出現了許多新演算法。它們技巧性強,在時間複雜度、空間複雜度和計算精度等方面各佔一定優勢,應用廣泛,效果顯著。

    演算法對我們真有那麼重要嗎?現在,這些看不見、摸不著的演算法正在掌控著我們與數字世界的互動,從谷歌網站上推薦圖書、電影和音樂的演算法到Facebook網站上推薦朋友的演算法,從操縱華爾街股票交易的演算法再到各種搜尋引擎的演算法及好萊塢預測電影票房的演算法,演算法似乎已無聲地滲入到我們的世界並重塑著我們身處的世界。有專家指出:計算機用來做決定的演算法正在以“隨風潛入夜,潤物細無聲”的方式,慢慢滲透進我們日常生活的方方面面。這些看不見摸不著的演算法正在慢慢掌控著我們與電子世界的相互交流,現在是一個“演算法為王”的時代。隨著演算法開始將其影響力延伸並塑造我們身處的世界,現在已經到了我們必須透徹地瞭解演算法的時候了。

    數學應用、應用數學,數學計算、計算數學,數學技術、技術數學,粗看起來,它們都和數學密切相連,都是以數學為工具,解決現實世界中遇到的各種各樣實際中遇到的問題;細分起來,在發展過程、研究方向、考慮問題的重點和評價優劣的標準等方面確有不少差異。但不管怎麼說,以數學為思維的方法,研究的工具,把實際問題經抽象處理,構建可用的數學模型,研究其中用到的各類演算法,編製成在計算機上可執行的程式,通過計算機上的實際計算和計算結果的分析處理,解決遇到的實際問題,這些都是它們應含有的思想和實際應用中要處理的問題。

    說到計算機,就像顯微鏡對醫學、望遠鏡對天文學一樣,是數學應用、數學計算、數學技術中不可缺少的裝置,時時、處處都要用到計算機,有的還要用到巨型計算機。計算機使數學原理得以實現,為數學應用開闢了無限廣闊的天地;計算機是具體化了的數學,現代數學的實驗室,進行現代數學研究和實際應用時必不可少的工具。這裡只能掛一漏萬,介紹一下計算機上資料的表示、數學運算及其誤差和幾個簡單的算例。

    資料(Data)是資訊的載體,是計算機加工處理的物件,描述客觀事物的數、字元,以及所有能輸入到計算機中並被計算機程式識別和處理的符號集合,它能夠被計算機識別、儲存和加工處理。它是計算機程式加工的原料,應用程式處理各種各樣的資料。計算機裡的資料可以是數值型資料,也可以是非數值型資料。數值型資料是一些整數、實數或複數,主要用於工程計算、科學計算和商務處理等;非數值型資料包括字元、文字、圖表、圖形、影象、語音等。資料元素(Data Element)是資料的基本單位。

    計算機中,以位(0或1)表示資料。資料的最小的定址單位稱為位元組(通常是八位),機器碼指令處理的單位,稱作字長。大部分對字長的指令解譯,主要以二進位制為主,如一個32位的字長,可以表示從0至232-1的無符號整數值,或者表示從-(232-1)至(232-1)有符號整數值。存在著特殊的算術指令,對字長中的位使用不同的解釋,以此作為浮點數。

    資料型別(Data type)是用來約束資料的解釋,有很多種,最簡單的就是數字。資料也可以是文字、影象、聲音等,可用於科學研究、設計、查證等。在程式語言中,常見的資料型別包括原始型別(如:整數、浮點數或字元)、多元組、記錄單元、代數資料型別、抽象資料型別、參考型別、類別以及函式型等。資料型別描述了數值的表示法、解釋和結構,並以演算法操作,或是物件在記憶體中的儲存區,或者其它儲存裝置,隨不同的計算機語言系統會有所不同。

    資料在計算機裡的基本運算和操作有如下四類:

    1.算術運算:加減乘除等運算;

    2.邏輯運算:或、且、非等運算;

    3.關係運算:大於、小於、等於、不等於等運算;

    4.資料傳輸:輸入、輸出、賦值等運算。

    用計算機高階語言研製的程式,大都含有數值計算;因此,在計算機應用中,進行數值計算是其最重要的功能之一。計算機語言中的數值表示及其運算和數學中的數值與運算有所不同,對此要有明確的認識和嚴格的區分,並在計算機上實施實際計算中給予足夠的重視和進行細緻的分析。在計算機各種不同的程式語言中,數值計算多采用32位(4位元組)的單字長或64位(8位元組)的雙字長作為一個數存單元,每一個數值都存放在計算機裡數存的一個單元中。數值的大小和數值的精度都受到一定限制。

    受計算機字長的限制,輸入到計算機裡的數會有原始誤差和舍入誤差,經計算得到結果的數含有運算誤差、傳遞誤差和累積誤差,計算公式進過簡化、離散、近似逼近等處理也會出現誤差。在計算機億萬次計算過程中,誤差的積累和傳遞是紙上手工計算中無法體會和了解的,兩者有很大不同,甚至在數學上成立的恆等式,在計算機上實施計算的過程中也會產生異化而不再成立。

    這裡將對上述問題及應注意的一些事項進行一些簡單扼要介紹。

    從我們接受基礎教育開始到中學學習結束,接觸到的數多是數學中的數,像小學中的自然數、小數、分數,中學時的負數、無理數、實數、複數等等,如53、123.618、2/3、-35.4、√2、3+10i(這裡,i= √-1,為虛數單位)等,用來表示一個明確的數;代數中,更是用英文字母表示非常廣義的數,如向量、矩陣等。但在計算機上和計算機語言中表示的數和運算,和數學中的數和運算卻有所不同,即計算機上計算公式裡的運算必須是計算機上可實際執行的運算,參與運算的數是有限小數或整數,並有一定的表示格式。

    在計算機內,所有的數均用二進位制表示,優點在於表示容易、物理實現簡單、節省裝置、代數運算簡單可靠、邏輯運算方便。在計算機裡,除二進位制數(用B表示)外、還有八進位制數(用O表示)、十進位制數(用D表示)、十六進位制數(用H表示)和二/十進位制數(全名為“二進位制編碼的十進位制數”,用BCD表示)等。

    計算機上的數,用二進位制的一位數碼錶示數的符號,稱為“數符”,且用“0”表示正數,“1”表示負數。小數點的位置隱含表示,以節省儲存空間。隱含的小數點位置有固定和可變兩種,分別稱為定點數和浮點數。

    1.定點數表示法

    定點整數:最高二進位制的一位數碼錶示數的符號,小數點位置約定在最低數值位的後面,用於表示整數。

    定點小數:最高二進位制的一位數碼錶示數的符號,小數點位置約定在符號位的後面,用於表示絕對值小於1的有限位小數。

    2.浮點數表示法

    階符:位於左側最高位二進位制的一位數字,表示階碼的符號;

    階碼:表示指數部分,階碼的位數決定數的範圍;

    數符:二進位制的一位數字,表示數的符號;

    尾數:小於1的小數,尾數的位數(長度)決定數的精度。

    在計算機語言中,把數分為實型數和復型數兩大類,分別和數學中的實數和複數相對應。在實型數中,又有整型數、定點數和浮點數之分,其中整型數相當於數學中的整數,定點數相當於數學中的小數,浮點數又稱作指數記數法,相當於數學中的科學計數法,不同只在於表示方法,例如,數學中的-79*105,在計算機上用浮點數表示為-0.79E7,其中-0.79為其尾數部分,E7為代表107的指數部分。那麼像√2 ,2/3等無理數、分數,在計算機及其語言中,又表示成什麼樣子呢?

    在BASIC語言中,有一個計算平方根的函式SQR(X),和數學中的√X起同樣作用,都是求X的平方根,如2的平方根SQR(2)=√2 ,只是SQR(X)被稱作函式,受計算機字長的限制,不再是無理數,而是一個有限字長的浮點數,取為√2 的近似值;像2/3,在BASIC語言中,稱作表示式,所得的是分子除以分母后所得的結果,只是為了計算機方便和清晰明瞭採用2/3這種表示方法。在計算機上使用的2/3,實際上是2除以3後的用有限字長表示的2/3的近似值。

    此外,在計算機語言中,數的大小有著明確規定的範圍。如在BASIC語言中,數的絕對值取值範圍為[2.938736*10-39,1.701412*1038];絕對值低於2.938736*10-39,計算機判為0,稱作下溢為0;超過上限1.701412*1038,計算機將顯示出錯資訊,稱為上溢位錯停機;而在數學當中,數的大小是無限的,範圍是(-∞,+∞)。

    在數學中,0.1=1/10,是一個不存在誤差的小數;但在計算機上,0.1用八進位制將無法精確表示,是一個含有誤差的數。

    計算機中的複數,把實部和虛部分開存放,通過內部子程式實現複數各種不同型別的運算。