268.和算法執行時間相關的因素

1.決定因素

1.1算法選用的策略node

1.2問題的規模算法

1.3編寫程序的語言數組

1.4編譯程序產生的機器代碼的質量函數

1.5計算機執行指令的速度post

 

 

2.其餘影響元素spa

 

 

3.問題的規模(時間複雜度)

3.1定義

  一個特定算法的「運行工做量」的大小,​只依賴於問題的規模(一般用整數量n表示),​或者說,它是問題規模的函數。​​3d

  假如,隨着問題規模 n 的增加,算法執行時間的增加率和 f(n) 的增加率相同,​則可記做:T (n) = O(f(n)), 稱T (n) 爲算法的(漸近)時間複雜度。​​​code

  一個算法是由控制結構(順序、分支和循環3種)和原操做(指固有數據類型的操做)構成的,算法的運行時間取決於二者的綜合效果。blog

 

 

 

3.2估算算法的時間複雜度

(Time Complexity)​排序

3.2.1定義

  從算法中選取一種對於所研究的問題來講是基本操做的原操做,​以該基本操做 在算法中重複執行的次數 做爲算法運行時間的衡量準則。

  ​「基本操做」 指的是,該操做重複執行次數和算法的運行時間成正比。

 

  算法的執行時間=∑原操做(i)的執行次數×原操做(i)的執行時間

  詳細​算法的執行時間與原操做執行次數之和成正比

 

  算法= 控制結構+ 原操做(固有數據類型的操做)

 

1兩個矩陣相乘
​​eg1:兩個矩陣相乘​
void mult(inta[], int b[], int&c[] ) ​{
// 以二維數組存儲矩陣元素,c爲 a 和 b的乘積
    for (i=1; i<=n; ++i){​ 
        for(j=1; j<=n; ++j) ​{ 
            c[i,j] = 0; 
            for(k=1; k<=n; ++k) 
                c[i,j] += a[i,k]*b[k,j]; 
            } 
    }
} 基本操做: 乘法操做時間複雜度:  O(n^3)    

2選擇排序

3起泡排序

4有以下遞歸函數fact(n),分析其時間複雜度
int fact(int n){ 
​if(n<=1) return(1);                (1) 
else return(n*fact(n-1));        (2)
}
解:設fact(n)的運行時間複雜函數是T(n),​
     該函數中語句(1)的運行時間是O(1),​
     語句(2)的運行時間爲:T(n-1)+O(1),
     其中O(1)爲基本運算時間,​
所以:  T(n) = O(1)+T(n-1)
            = O(1)+O(1)+T(n-2)
            = …… 
            = (n-1)*O(1)+T(1) 
            = n*O(1) 
            = O(n)則fact(n)的時間複雜度爲O(n)。​​

 

3.2.2分析算法時間複雜度的通常步驟 

 

 

 

 

3.2.3漸進符號

  設n爲算法中的問題規模,一般用大O、大Ω和Θ等三種漸進符號表示算法的執行時間與n之間的一種增加關係。

 

3.2.3.1 大O符號

定義

  定義1(大O符號),f(n)=O(g(n))(讀做「f(n)是g(n)的大O」)當且僅當存在正常量c和n0,使當n≥n0時,f(n)≤cg(n),即g(n)爲f(n)的上界。

 

 如3n+2=O(n),由於當n≥2時,3n+2≤4n。
 10n2+4n+2=O(n4),由於當n≥2時,10n2+4n+2≤10n4。

 

  大O符號用來描述增加率的上界,表示f(n)的增加最多像g(n) 增加的那樣快,也就是說,當輸入規模爲n時,算法消耗時間的最大值。這個上界的階越低,結果就越有價值,因此,對於10n2+4n+2,O(n2)比O(n4) 有價值。

 

  一個算法的時間用大O符號表示時,老是採用最有價值的g(n)表示,稱之爲「緊湊上界」或「緊確上界」。

  通常地,若是

 

 

 

經常使用的幾種時間複雜度的關係

說明:

1.在難以精確計算基本操做執行次數(或語句頻度)的狀況下,只需求出它關於n的增加率或階便可2.一個算法的時間複雜度能夠具體分爲最好、最差(又稱最壞)和平均三種狀況討論。​

除特別說明外,正常均指最壞狀況下的時間複雜度。

 

例子

1兩個矩陣相乘
​​eg1:兩個矩陣相乘​
void mult(inta[], int b[], int&c[] ) ​{ // 以二維數組存儲矩陣元素,c爲 a 和 b的乘積 for (i=1; i<=n; ++i){​ for(j=1; j<=n; ++j) ​{ c[i,j] = 0; for(k=1; k<=n; ++k) c[i,j] += a[i,k]*b[k,j]; } } } 基本操做: 乘法操做時間複雜度: O(n^3) 

2選擇排序

3起泡排序

4有以下遞歸函數fact(n),分析其時間複雜度
int fact(int n){ ​if(n<=1) return(1); (1) else return(n*fact(n-1)); (2) } 解:設fact(n)的運行時間複雜函數是T(n),​ 該函數中語句(1)的運行時間是O(1),​ 語句(2)的運行時間爲:T(n-1)+O(1), 其中O(1)爲基本運算時間,​ 所以: T(n) = O(1)+T(n-1) = O(1)+O(1)+T(n-2) = …… = (n-1)*O(1)+T(1) = n*O(1) = O(n)則fact(n)的時間複雜度爲O(n)。​​

 

 

3.2.3.2 大Ω符號

  定義2(大Ω符號),f(n)= Ω(g(n))(讀做「f(n)是g(n)的大Ω」)當且僅當存在正常量c和nθ,使當n≥n0時,f(n)≥cg(n),即g(n)爲f(n)的下界。

 

  如3n+2=Ω(n),由於當n≥1時,3n+2≥3n。
  10n2+4n+2=Ω(n2),由於當n≥1時,10n2+4n+2≥n2。  

 

  大Ω符號用來描述增加率的下界,表示f(n)的增加最少像g(n) 增加的那樣快,也就是說,當輸入規模爲n時,算法消耗時間的最小值。
與大O符號對稱,這個下界的階越高,結果就越有價值,因此,對於10n2+4n+2,Ω(n2)比Ω(n) 有價值。一個算法的時間用大Ω符號表示時,老是採用最有價值的g(n)表示,稱之爲「緊湊下界」或「緊確下界」。

  通常地,若是,有

 

 

3.2.3.3大Θ符號

  定義3(大Θ符號),f(n)= Θ(g(n))(讀做「f(n)是g(n)的大Θ」)當且僅當存在正常量c一、c2和n0,使當n≥n0時,有c1g(n)≤f(n)≤c2g(n),即g(n)與f(n)的同階。

 

  如3n+2=Θ (n),10n2+4n+2=Θ(n2)。


  通常地,若是,有f(n)=Θ(nm)。

  大Θ符號比大O符號和大Ω符號都精確,f(n)=Θ(g(n),當且僅當g(n)既是f(n)的上界又是f(n)的下界。

 

 

3.2.3.4關係

 

 

 

3.3算法的最好、最壞和平均狀況

  設一個算法的輸入規模爲n,Dn是全部輸入的集合,任一輸入I∈Dn,P(I)是I出現的機率,有ΣP(I) =1,T(I)是算法在輸入I下所執行的基本語句次數,則該算法的平均執行時間爲:A(n)=。  

  也就是說算法的平均狀況是指用各類特定輸入下的基本語句執行次數的帶權平均值。

  算法的最好狀況爲:G(n)=,是指算法在全部輸入I下所執行基本語句的最少次數。

  算法的最壞狀況爲:W(n)=,是指算法在全部輸入I下所執行基本語句的最大次數。

 

 

4.算法選用的策略

4.3非遞歸算法的時間複雜度分析

  對於非遞歸算法,分析其時間複雜度相對比較簡單,關鍵是求出表明算法執行時間的表達式。
  一般是算法中基本語句的執行次數,是一個關於問題規模n的表達式,而後用漸進符號來表示這個表達式即獲得算法的時間複雜度。

 

【例1.6】給出如下算法的時間複雜度。
void func(int n)
{   int i=1,k=100;
    while (i<=n)
    {  k++;
       i+=2;
    }
}
  解:算法中基本語句是while循環內的語句。
  設while循環語句執行的次數爲m,i從1開始遞增,最後取值爲1
+2m,有: i=1+2m≤n f(n)=m≤(n-1)/2=O(n)。   該算法的時間複雜度爲O(n)。

 

 

 

4.2遞歸算法的時間複雜度分析

  遞歸算法是採用一種分而治之的方法,把一個「大問題」分解爲若干個類似的「小問題」來求解。
  對遞歸算法時間複雜度的分析,關鍵是根據遞歸過程創建遞推關係式,而後求解這個遞推關係式,獲得一個表示算法執行時間的表達式,最後用漸進符號來表示這個表達式即獲得算法的時間複雜度。

 

【例1.7】有如下遞歸算法:
void mergesort(int a[],int i,int j)
{   int m;
    if (i!=j)
    {     m=(i+j)/2;
        mergesort(a,i,m);
        mergesort(a,m+1,j);
        merge(a,i,j,m);
    }
}
    其中,mergesort()用於數組a[0..n-1](設n=2k,這裏的k爲正整數)的歸併排序,
  調用該算法的方式爲: mergesort(a,
0,n-1); 另外merge(a,i,j,m)用於兩個有序子序列a[i..j]和a[j+1..m]的有序合併,
  是非遞歸函數,它的時間複雜度爲O(n)(這裏n=j-i+1)。分析上述調用的時間複雜度。
  解:設調用mergesort(a,0,n-1)的執行時間爲T(n),
由其執行過程獲得如下求執行時間的遞歸關係(遞推關係式): T(n)=O(1) 當n=1 T(n)=2T(n/2)+O(n) 當n>1 其中,O(n)爲merge()所需的時間,設爲cn(c爲正常量)。所以: T(n) = 2T(n/2)+cn=2[2T(n/22)+cn/2]+cn=22T(n/22)+2cn = 23T(n/23)+3cn = … = 2kT(n/2k)+kcn = nO(1)+cnlog2n=n+cnlog2n //這裏假設n=2k,則k=log2n = O(nlog2n)

 

【例1.8】求解梵塔問題的遞歸算法以下,分析其時間複雜度。
void Hanoi(int n,char x,char y,char z)
{  if (n==1)
      printf("將盤片%d從%c搬到%c\n",n,x,z);
   else
   {   Hanoi(n-1,x,z,y);
       printf("將盤片%d從%c搬到%c\n",n,x,z);
    Hanoi(n-1,y,x,z);
   }
}

 

   解:設調用Hanoi(n,x,y,z)的執行時間爲T(n),由其執行過程獲得如下求執行時間的遞歸關係(遞推關係式):
T(n)=O(1)      當n=1
T(n)=2T(n-1)+1      當n>1
T(n) = 2[2T(n-2)+1]+1=22T(n-2)+1+21 = 23T(n-3)+1+21+22 = … = 2n-1T(1)+1+21+22+…+2n-2 = 2n-1 = O(2n)

 

 

 

相關文章
相關標籤/搜索