《大話數據結構》閱讀總結(二)算法

(二)算法

算法是解決特定問題求解步驟的描述,在計算機中表現爲指令的有限序列,而且每條指令表示一個或多個操做。算法

2.1 算法的特性

算法具備五個基本特性。數組

輸入 算法具備零個或多個輸入
輸出 算法至少有一個或多個輸出
有窮性 算法在執行有限的步驟以後,自動結束而不會出現無限循環,而且一個步驟在可接受的時間內完成。
肯定性 算法的每個步驟都具備肯定的含義,不會出現二義性。
可行性 算法的每一步都必須是可行的,也就是說,每一步都可以經過執行有限次數完成。

2.2 算法設計的要求

正確性 算法的正確性是指算法至少應該具備輸入、輸出和加工處理無歧義性、能正確反映問題的需求、可以獲得問題的正確答案。
大致分爲如下四個層次:
1 算法程序沒有語法錯誤。
2 算法程序對於合法的輸入數據可以產生知足要求的輸出結果。
3 算法程序對於非法的輸入數據可以得出知足規格說明的結果。
4 算法程序對於精心選擇的,甚至刁難的測試數據都有知足要求的輸出結果。
通常狀況,以層次3做爲一個算法是否正確的標準。
可讀性 算法設計的另外一目的是爲了便於閱讀、理解和交流。
健壯性 當輸入數據不合法時,算法也能作出相關處理,而不是產生異常或莫名其妙的結果。
時間效率高和存儲量低 設計算法應該儘可能知足時間效率高和存儲量低的需求。

2.3 算法效率的度量方法

算法效率大都指算法的執行時間,經過對算法的數據測試,利用計算機的計時功能,來計算不一樣算法的效率是高仍是低。函數

2.3.1 過後統計方法

主要是經過設計好的測試程序和數據,利用計算機計時器對不一樣算法編制的程序的運行時間進行比較,從而肯定算法效率的高低。性能

缺陷:測試

  1. 必須依據算法事先編制好程序,須要花費大量的時間和精力。
  2. 時間的比較依賴計算機硬件和軟件等環境因素,有時會掩蓋算法自己的優劣。
  3. 算法的測試數據設計困難,程序的運行時間每每還與測試數據的規模有很大關係,效率高的算法在小的測試數據面前得不到體現。

基於過後統計方法有上述缺陷,不予採納。spa

2.3.2 事前分析估算方法

在計算機程序編制前,依據統計方法對算法進行估算。設計

算法執行時間的受影響因素
1 算法採用的策略、方法 算法好壞的根本
2 編譯產生的代碼質量 軟件支持
3 問題的輸入規模 輸入量的多少
4 機器執行指令的速度 硬件性能

PS: 拋開與計算機硬件、軟件有關的因素。一個算法的運行時間,依賴於算法的好壞和問題的輸入規模編譯

咱們不關心編寫程序的設計語言,也不關心程序跑在什麼計算機中,咱們只關心它所實現的算法。最終,在分析程序的運行時間時,最重要的是把程序當作是獨立於程序設計語言的算法或一系列步驟table

綜上所述,測定運行時間最可靠的方法就是計算對運行時間有消耗的基本操做的執行次數。運行時間與這個計數成正比。
而咱們在分析一個算法的運行時間時,重要的是把基本操做的數量與輸入規模關聯起來,即基本操做的數量必須表示成輸入規模的函數程序設計

舉例:1 + 2 + 3 + ... + n 求和算法
算法 輸入規模 基本操做的執行次數(輸入規模的函數)
遍歷1到n累加 n f(n) = n
(1 + n) * n / 2 n f(n) = 1

2.4 函數的漸近增加

函數的漸近增加:給定兩個函數 f(n) 和 g(n),若是存在一個整數 N,使得對於全部的 n > N,f(n) 老是比 g(n) 大,那麼,咱們說 f(n) 的增加漸近快於 g(n)

兩個算法函數進行比較時,隨着 n 的增加,咱們發現以下幾點規律:

  1. 加法常量能夠忽略
  2. 與最高次項相乘的常數並不重要
  3. 最高次項的指數大的,函數隨着 n 的增加,結果也會增加的特別快

綜上所述,判斷一個算法的效率時,函數中的常數和其餘次要項經常能夠忽略,而更應該關注主項(最高階項)的階數

判斷一個算法的好壞,少許的數據是不能作出準確判斷的。
某個算法,隨着n的增大,它會愈來愈優於另外一個算法,或者愈來愈差於另外一個算法
即事前估算方法的理論依據,經過算法時間複雜度來估算算法時間效率。

2.5 算法時間複雜度

在進行算法分析時,語句總的執行次數 T(n) 是關於問題規模 n 的函數,進而分析 T(n) 隨 n 的變化狀況並肯定 T(n) 的數量級。算法的時間複雜度,也就是算法的時間量度,記做:T(n) = O(f(n))。它表示隨問題規模n的增大,算法執行時間的增加率和 f(n) 的增加率相同,稱做算法的漸近時間複雜度,簡稱爲時間複雜度。其中 f(n) 是問題規模 n 的某個函數。

這樣用大寫O()來體現時間複雜度的記法,稱之爲大O記法

2.5.1 推導大O階方法

  1. 用常數1取代運行時間中的全部加法常數。
  2. 在修改後的運行次數函數中,只保留最高階項。
  3. 若是最高階項存在且不是1,則去除與這個項相乘的常數。

2.5 常見的時間複雜度

執行次數函數 f(n) 階 O(f(n)) 非正式術語
12 O(1) 常數階
6n^3 + 2n^2 + 3n + 4 O(n3) 立方階
3n^2 + 2n + 1 O(n^2) 平方階
5log2(n) + 20 O(logn) 對數階
2n + 3nlog2(n) + 19 O(nlogn) nlogn階
6n^3 + 2n^2 + 3n + 4 O(n^3) 立方階
2^n O(n^2) 指數階

經常使用時間複雜度所耗費的時間 從小到大依次是:
O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)

2.6 最壞狀況與平均狀況

查找一個有n個隨機數字數組的某個數字,最好的狀況是第一個數字就是,那麼算法的時間複雜度爲 O(1) ,但也有可能這個數字就在最後一個位置上待着,那麼算法的時間複雜度就是 O(n) ,這是最壞的一種狀況。

最壞狀況運行時間是一種保證,那就是運行時間將不會再壞了。在應用中,這是一種最重要的需求,一般,除非特別指定,咱們提到的運行時間都是最壞狀況的運行時間。

平均運行時間是全部狀況中最有意義的,由於它是指望的運行時間。

對算法的分析,一種方法是計算全部狀況的平均值,這種時間複雜度的計算方法稱爲平均時間複雜度。另外一種方法是計算最壞狀況下的時間複雜度,這種方法稱爲最壞時間複雜度通常在沒有特殊說明的狀況下,都是指最壞時間複雜度

2.7 算法空間複雜度

咱們在寫代碼時,徹底能夠用空間來換取時間。

算法的空間複雜度經過計算算法所需的存儲空間實現,算法空間複雜度的計算公式記做: S(n) = O(f(n)) ,其中, n 爲問題的規模,f(n) 爲語句關於 n 所佔存儲空間的函數。

一般,咱們都使用「時間複雜度」來指運行時間的需求,使用「空間複雜度」指空間需求。當不用限定詞地使用「複雜度時」,一般指時間複雜度。

相關文章
相關標籤/搜索