1. 程式人生 > >資料結構(二):演算法及其描述

資料結構(二):演算法及其描述

一、演算法及其描述

1、什麼是演算法

資料元素之間的關係有邏輯關係和物理關係,對應的操作有邏輯結構上的操作功能和具體儲存結構上的操作實現。

具體儲存結構上的操作實現方法 稱為演算法。

確切地說,演算法是對特定問題求解步驟的一種描述,它是指令的有限序列,其中每一條指令包含一個或多個計算機操作。

一個演算法具有如下特性:

  • 有窮性:一個演算法 必須總是 (對任何合法的輸入值)在執行有窮步後結束,而且每一步都要在有窮的時間內完成。也就是說,一個演算法對任意一組合法的輸入值,在執行有窮步驟後一定能結束。

  • 確定性:對於每種情況下演算法應該執行的操作,在演算法中都應該有明確的規定,使演算法的執行者或閱讀者能夠明確其含義及如何執行。並且在任何條件下,演算法只能由一條執行路徑。

    也就是說,對於任意一組給定的合法輸入值,演算法要執行的操作是確定的。

  • 可行性:演算法中的所有操作都必須足夠基本,都可以通過已經實現的基本操作運算有限次實現。

  • 有輸入:作為演算法加工物件的量值,通常體現為演算法中的一組變數。有些輸入需要在演算法執行中給出,而有些演算法看似沒有輸入,實際上已經內嵌在程式碼中。

  • 有輸出:輸出是與輸入由確定關係的一組量值,是演算法進行資訊加工後的到的結果,這種確定關係就是演算法的功能。

2、演算法描述

我們有許多方法來描述一個演算法,如:

設計一個演算法:求解一元二次方程組

我們分別用文字描述和 C/C++語言來描述設計的演算法:

語言描述:
  1. 計算 d = b*b - 4*a*c
  2. 如果 d > 0,則轉第 5步
  3. 如果 d = 0,則轉第 9步
  4. 如果 d < 0,則轉第 12步
  5. 計算 x1 = (-b + sqrt(d)) / (2*a)
  6. 計算 x2 = (-b - sqrt(d)) / (2*a)
  7. 顯示 x1和 x2的值
  8. 轉第 13步
  9. 計算 x = (-b) / (2*a)
  10. 顯示 x的值
  11. 轉第 13步
  12. 顯示沒有實根
  13. 演算法結束
C/C++語言描述
void solution(float a, float b, float c){
    float d, x1, x2, x;
    d = b*b - 4*a*c;
    if(d>0){
        x1 = (-b + sqrt(d)) / (2*a);
        x2 = (-b - sqrt(d)) / (2*a);
        printf("兩個實根是:x1=%f, x2=%f\n", x1, x2);
    }
    else if(d==0){
        x = (-b) / (2*a);
        printf("一個實根是:x=%f\n", x);
    }
    else{
        printf("不存在實根\n");
    }
}

從上面的兩個例子我們可以看出用 C/C++來描述的演算法結構更清晰(編寫的程式結構化更高,對 d的三種不同情況的處理一目瞭然)。

3、演算法分析

在一個演算法設計好後,還需要對其進行分析來確定一個演算法的好壞。

演算法設計的目標
  1. 正確性:要求演算法能夠正確地預先規定的功能和效能要求。這是最重要也是最基本的標準。
  2. 可使用性:要求演算法能夠方便地使用,對使用者要友好。
  3. 可讀性:演算法應該易於人地理解。為了達到這個要求,演算法的邏輯必須是清晰的、簡單的,程式碼應該是結構化的。
  4. 健壯性:演算法應該具有很好的容錯性,能夠對不合理的資料進行檢查,不經常出現異常中斷或者宕機的現象。
  5. 高效率和低儲存量
演算法效率分析

通常由兩種衡量演算法效率的方法:事後統計法和事前分析估演算法。

事後分析法存在以下缺點:

  1. 必須執行程式
  2. 存在其他因素掩蓋演算法本質

所以我們一般採用事前分析法。

一般來說,一個程式的執行速度不僅和演算法有關,還和執行程式的計算機和所處計算機環境有關。所以我們需要撇開這些計算機軟體、硬體有關的因素,僅考慮演算法本身的效率高低。

一個演算法是由控制結構(順序、分支和迴圈)和原操作(固有的資料型別的操作,或者可以理解為分支和迴圈裡要執行的操作)構成的。

為了比較同一問題的不同演算法,通常從演算法中選取一種對所研究的問題來說是基本運算的原操作,演算法執行的時間大致為原操作的執行時間和被執行的次數的乘積。

顯然,在一個演算法中,執行原操作的次數越少,其執行時間也就相對地越少;執行的原操作次數越多,其執行時間也就相對地越多。

所以通常把演算法中執行原操作地次數稱為演算法地時間複雜度,也就是說,一個演算法地時間複雜度就是指其原操作在演算法中反覆執行的次數。

演算法中基本運算次數(原操作)T(n)是問題規模 n的某個函式,記作:

"O"的定義為:若 f(n)是正整數 n的一個函式,則 T(n)=O(f(n))表示存在一個正整數 M,使得當 n>=n0時都滿足

也就是說,我們只需要求出 f(n)的最高階,而忽略其低階項和常係數,例如:

演算法儲存空間分析

一個演算法的儲存量包括輸入資料所佔空間、程式本身所佔空間和輔助變數所佔空間。

在對演算法進行儲存空間分析時,只考慮輔助變數所佔空間。所以,空間複雜度是對一個演算法在執行過程中臨時佔用的儲存空間大小的量度。

與時間複雜度類似,空間複雜度也是問題規模 n的函式,也以數量級的形式給出,記作:

若所需額外空間相對於輸入資料量來說是常數,則稱此演算法為原地工作或就地工作。若所需儲存量依賴於輸入,則通常按最壞的情況考慮。

轉載自:
資料結構教程(第二版)
李春葆 等 編著
清華大學出版社
ISBN:978-7-302-14229-4