演算法複雜度

2021-09-20 03:23:09 字數 2909 閱讀 6380

【對於乙個給定的演算法,通常要評估其正確性和執行效率的高低。演算法的正確性評估不在本文範圍之內,本文主要討論從演算法的時間複雜度特性去評估演算法的優劣。】

程式是用來解決問題的,是由多個步驟或過程組成的,這些步驟和過程就是解決問題的演算法。解決乙個問題有多種方法,也就有多種演算法。每一種演算法都可以達到解決問題的目的,但花費的成本和時間不盡相同,從節約成本和時間的角度考慮,需要找出最優演算法。那麼,如何衡量乙個演算法的好壞呢?

顯然,選用的演算法應該是正確的(演算法的正確性不在此論述)。除此之外,通常有三個方面的考慮:

(1)演算法在執行過程中所消耗的時間;

(2)演算法在執行過程中所佔資源的大小,例如,占用記憶體空間的大小;

(3)演算法的易理解性、易實現性和易驗證性等等。

衡量乙個演算法的好壞,可以通過前面提出的三個方面進行綜合評估。從多個候選演算法中找出執行時間短、資源占用少、易理解、易實現的演算法。然而,現實情況卻不盡人意。往往是,乙個看起來很簡便的演算法,其執行時間要比乙個形式上覆雜的演算法慢的多;而乙個執行時間較短的演算法往往占用較多的資源。

因此,在不同情況下需要選擇不同的演算法。在實時系統中,對系統響應時間要求高,則盡量選用執行時間少的演算法;當資料處理量大,而儲存空間較少時,則盡量選用節省空間的演算法。本文主要討論演算法的時間特性,並給出演算法在時間複雜度上的度量指標。

乙個演算法在執行過程中所消耗的時間取決於下面的因素:

(1)演算法所需資料輸入的時間;

(2)演算法編譯為可執行程式的時間;

(3)計算機執行每條指令所需的時間;

(4)演算法語句重複執行的次數。

其中(1)依賴於輸入裝置的效能,若是離線輸入,則輸入資料的時間可以忽略不計。(2)(3)取決於計算機本身執行的速度和編譯程式的效能。因此,習慣上將演算法語句重複執行的次數作為演算法的時間量度。

例如:add函式僅包含一條語句,執行次數為1次;madd函式包含n次的單重for迴圈,每次迴圈都執行x=x+1語句,因此執行次數為n次;loopadd函式包含n次的雙重迴圈,在第二層迴圈執行x=x+1語句,因此執行次數為n*n次,即n^2次。

上面的例子並沒有把迴圈本身執行的次數算進去,下面給出2個執行次數計算較為精確的例子。

上面的程式段執行次數為2n+3次。

再看下面矩陣相加的例子。

矩陣相加的執行次數為2n^2+2n+2。

一般情況下,n為問題規模(大小)的量度,如陣列的長度、矩陣的階、圖中的頂點數等等。

對於前面add函式來說,問題規模量度為常數(1);對於陣列排序問題來說,問題規模量度為輸入陣列的長度(記為n);對於n階矩陣相加來說,問題規模量度為矩陣階數的平方(記為n^2)。

為了給出演算法通用的時間量度,用數學概念來描述演算法的執行次數,可以把乙個演算法中語句的執行次數稱為語句頻度或時間頻度,記為t(n)。當問題規模n不斷變化時,時間頻度t(n)也會不斷變化,我們需要評估當n不斷變化時,時間頻度t(n)的變化規律。

若有某個輔助函式f(n),當n趨向於無窮大時,如果t(n)/ f(n)的極限為不等於零的常數,則認為t(n)與f(n)是同量級的函式,記作:t(n) =o(f(n)),o(f(n))稱為演算法的漸進時間複雜度,簡稱時間複雜度。

漸進時間複雜度表示的意義是:

(1)在較複雜的演算法中,進行精確分析是非常複雜的;

(2)一般來說,我們並不關心t(n)的精確度量,而只是關心其量級。

t (n) = o(f (n)) 表示存在乙個常數c,當n趨於正無窮大時,總有t (n) ≤ c * f(n),其意義是t(n)在n趨於正無窮大時跟f(n)基本接近,因此完全可以用f(n)來表示t(n)。

o(f (n))通常取執行次數中最高次方或最大指數部分的項。例如:

(1)陣列元素相加為2n+3 = o(n)

(2)矩陣相加為2n^2+2n+1 = o(n^2)

(3)矩陣相乘為2n^3+4n^2+2n+2 = o(n^3)

在各種不同的演算法中,若演算法語句的執行次數為常數,則演算法的時間複雜度為o(1),按數量級遞增排列,常見的時間複雜度量有:

(1)o(1):常量階,執行時間為常量

(2)o(logn):對數階,如二分搜尋演算法

(3)o(n):線性階,如n個數內找最大值

(4)o(nlogn):對數階,如快速排序演算法

(5)o(n^2):平方階,如選擇排序,氣泡排序

(6)o(n^3):立方階,如兩個n階矩陣的乘法運算

(7)o(2^n):指數階,如n個元素集合的所有子集的演算法

(8)o(n!):階乘階,如n個元素全部排列的演算法

下圖給出了隨著n的變化,不同量級的時間複雜度變化曲線。

評估演算法時間複雜度的具體步驟是:

(1)找出演算法中重複執行次數最多的語句的頻度來估算演算法的時間複雜度;

(2)保留演算法的最高次冪,忽略所有低次冪和高次冪的係數;

(3)將演算法執行次數的數量級放入大ο記號中。

例如,下列三個簡單的程式段:

在程式段(a)中,語句x=x+1不在任何乙個迴圈體內,則它的時間頻度為1,其執行時間是個常量;而(b)中,同一語句被重複執行n次,其時間頻度為n;顯然在(c)中,該語句的頻度為n^2。由此,這三個程式段的時間複雜度為o(1)、o(n)、o(n^2)。分別為常量、線性階和平方階。

對於較為複雜的演算法,可以將它們分割成容易估算的幾個部分,然後利用o的求和原則得到整個演算法的時間複雜度。例如,若演算法的兩個部分的時間複雜度分別為t1(n)=o(f(n))和t2(n)=o(g(n)),則總的時間複雜度為:

t(n)= t1(n)+ t2(n)=o(max(f(n), g(n)))

然而,很多演算法的執行時間不僅依賴於問題的規模,也與處理的資料集有關。例如,有的排序演算法對某些原始資料(如自小至大有序),則其時間複雜度為o(n),而對另一些資料可達o(n^2)。因此,在估算演算法的時間複雜度時,均以資料集中最壞的情況來估算。

文章小結

評估演算法時間複雜度的要點是:如果乙個演算法的執行次數是 t(n),那麼只保留最高次項,同時忽略最高項的係數後得到函式 f(n),此時演算法的時間複雜度就是 o(f(n))。

演算法複雜度 時間複雜度和空間複雜度

1 時間複雜度 1 時間頻度 乙個演算法執行所耗費的時間,從理論上是不能算出來的,必須上機執行測試才能知道。但我們不可能也沒有必要對每個演算法都上機測試,只需知道哪個演算法花費的時間多,哪個演算法花費的時間少就可以了。並且乙個演算法花費的時間與演算法中語句的執行次數成正比例,哪個演算法中語句執行次數...

演算法複雜度 時間複雜度和空間複雜度

演算法複雜度 時間複雜度和空間複雜度 關鍵字 演算法複雜度 時間複雜度 空間複雜度 1 時間複雜度 1 時間頻度 乙個演算法執行所耗費的時間,從理論上是不能算出來的,必須上機執行測試才能知道。但我們不可能也沒有必要對每個演算法都上機測試,只需知道哪個演算法花費的時 間多,哪個演算法花費的時間少就可以...

演算法複雜度 時間複雜度和空間複雜度

演算法的時間複雜度是指執行演算法所需要的計算工作量。n稱為問題的規模,當n不斷變化時,時間頻度t n 也會不斷變化。但有時我們想知道它變化時呈現什麼規律。為此,我們引入時間複雜度概念。一般情況下,演算法中基本操作重複執行的次數是問題規模n的某個函式,用t n 表示,若有某個輔助函式f n 存在乙個正...