《大話資料結構》讀後總結(四)

徐曙輝發表於2019-03-22

一、演算法

1、演算法效率的度量方法

1.1 事後統計方法
  • 通過設計好的測試程式和資料,利用計算機計時器對不同演算法編制的程式的執行時間進行比較,從而確定演算法效率的高低。該方法具有很大缺陷,不予採納。

    1.必須依據演算法事先編制好程式,花費時間和人力

    2.時間的比較依賴計算機硬體和軟體等環境因素,有時會掩蓋演算法本身的優劣。

    3.演算法的測試資料設計困難,並且程式的執行時間往往還與測試資料的規模有很大關係,效率高的演算法在小的測試資料面前往往得不到體現。

1.2 事後統計方法
  • 在計算機程式編制前,依據統計方法對演算法進行估算。

  • 經過分析,我們發現,一個用高階程式語言編寫的程式在計算機上執行時所消耗的時間取決於下列因素:

    1.演算法採用的策略、方法。

    2.編譯產生的程式碼質量。

    3.問題的輸入規模。

    4.機器執行指令的速度。

  • 拋開這些與計算機硬體、軟體有關的因素,一個程式的執行時間,依賴於演算法的好壞和問題的輸入規模。所謂問題輸入規模是指輸入量的多少。

  • 下面用兩種求和演算法進行舉例。 第一種

int i, sum = 0,n = 100;     /* 執行1次 */
for (i = 1; i <= n; i++)    /* 執行了n+1次 */
{
    sum = sum + i;          /* 執行n次 */
}
printf("%d", sum);          /* 執行1次 */
複製程式碼

第二種

int sum = 0,n = 100;      /* 執行一次 */
sum = (1 + n) * n / 2;    /* 執行一次 */
printf("%d", sum);        /* 執行一次 */
複製程式碼
  • 第一種演算法,執行了1+(n+1)+n+1次=2n+3次;
  • 第二種演算法,是1+1+1=3次。
  • 事實上兩個演算法的第一條和最後一條語句是一樣的,所以我們關注的程式碼其實是中間的那部分,我們把迴圈看作一個整體,忽略頭尾迴圈判斷的開銷,那麼這兩個演算法其實就是n次與1次的差距。 第三種
int i, j, x = 0, sum = 0, n = 100;    /* 執行一次 */
for (i = 1; i <= n; i++)
{
    for (j = 1; j <= n; j++)
    {
        x++;    /* 執行n×n次 */
        sum = sum + x;
    }
}
printf("%d", sum);    /* 執行一次 */
複製程式碼

這個例子中,i從1到100,每次都要讓j迴圈100次,而當中的x++和sum=sum+x;其實就是1+2+3+...+10000,也就是100^2次,所以這個演算法當中,迴圈部分的程式碼整體需要執行n^2次。

測定執行時間最可靠的方法就是計算對執行時間有消耗的基本操作的執行次數。執行時間與這個計數成正比。

同樣問題的輸入規模是n,求和演算法的第一種,求1+2+...+n需要一段程式碼執行n次。那麼這個問題的輸入規模使得運算元量是f(n)=n,顯然執行100次的同一段程式碼規模是運算10次的10倍。而第二種,無論n為多少,執行次數都為1,即f(n)=1;第三種,運算100次是運算10次的1000倍。因為它是f(n)=n^2。

分析一個演算法的執行時間時,重要的是把基本操作的數量與輸入規模關聯起來,即基本操作的數量必須表示成輸入規模的函式。

image

隨著n值的越來越大,它們在時間效率上的差異也就越來越大。

歡迎掃描下方二維碼,持續關注:

image

網際網路工程師(id:phpstcn),我們一起學習,一起進步

相關文章