1. 程式人生 > >資料結構與演算法之美 03

資料結構與演算法之美 03

複雜度分析(上):如何分析、統計演算法的執行效率和資源消耗

資料結構和演算法本身解決的是“快”和“省”的問題,即如何讓程式碼執行地更快,如何讓程式碼更省儲存空間。

一、為什麼需要複雜度分析

  • 測試結果非常依賴測試環境
  • 測試結果受資料規模的影響很大

二、大O複雜度表示法

演算法的執行效率,粗略的講,就是演算法程式碼執行的時間。

估算這段程式碼的執行時間。

int cal(int n){
    int sum = 0;
    int i = 1;
    int j = 1;
    for ( ; i<=n; ++i){
        for ( ;, j<=n; ++j){
            sum = sum + i * j;
        }
    }
    return sum;
}

整段程式碼總的執行時間T(n) = (2n^2 + 2n + 3)*unit_time。

所有程式碼的執行時間T(n)與每行程式碼的執行次數n成正比。T(n) = O(f(n))。

T(n)表示執行程式碼的時間;n表示資料規模的大小;f(n)表示每行程式碼執行的次數綜合。公式中的O表示程式碼執行時間T(n)與f(n)表示式成正比。

所以這個例子中T(n) = O(2n^2 + 2n + 3)。

這就是大O時間複雜度表示法。大O時間複雜度實際上並不具體代表程式碼真正的執行時間,而是代表程式碼執行時間隨資料規模增長的變化趨勢,所以,也叫做漸進時間複雜度

三、時間複雜度分析

  • 只關注迴圈執行次數最多的一段程式碼
  • 加法法則:總複雜度等於量級最大的那段程式碼的複雜度
  • 乘法法則:巢狀程式碼的複雜度等於巢狀內外程式碼複雜度的乘積

四、幾種常見時間複雜度

常量階:O(1)          指數階:O(2^n)           對數階:O(logn)             階乘階:O(n!)

線性階:O(n)          線性對數階O(nlogn)    平方階:O(n^2)、立方階:O(n^3)、、、k次方階O(n^k)

多項式階:隨著資料規模的增長,演算法的執行時間和空間佔用按照多項式的比例增長。包括常量階、對數階、線性階、線性對數階、平方階、立方階等;

非多項式階:隨著資料規模的增長,演算法的執行時間和空間佔用暴增,這類演算法效能極差。包括指數階和階乘階。

對數階舉例

i = 1;
while (i <= n){
    i = i*2;
}

五、空間複雜度分析

空間複雜度表示演算法的儲存空間與資料規模之間的增長關係,又稱漸進空間複雜度。

void print(int n){
    int i = 0;
    int [] a = new int[n];
    for (i; i<n; ++i){
        a[i] = i * i;
    }

    for (i = n-1; i>=0; --i){
        print out a[i]
    }
}

第二行程式碼中,我們申請了一個空間儲存變數i,但是它是常量階的,跟資料規模n沒有關係,所以可以忽略。第三行中,我們申請了一個大小為n的int型別資料。所以整段程式碼的空間複雜度就是O(n)。

熟能生巧