《算法之道》精華 經典算法部分

《算法之道》精華 經典算法部分

  • 本書作者鄒恆明,作者另有一本書《數據結構之弦》,以及《操作系統之哲學原理》都是很好的書
  • 這本書可以算得上是深入淺出,文筆很好,作者添加了很多自己的思考
  • 本文包括經典算法部分

第十章 排序與次序

  • 插入排序
    • 從無序部分抽取一張插入有序部分
    • 爲原地排序,無需佔用臨時存儲空間
    • 最優情況下爲O(n),平均O(n^2)
  • 折半插入排序
    • 插入時使用二分查找
  • 歸併排序
    • 分治,從中間分解,分別排序後進行仔細的合併
    • 異地排序,需要佔用額外空間
    • n>=30時性能比插入排序更好。複雜度固定爲O(nlog(n))
  • 快排
    • 分治,複雜的部分在於分解,而歸併複雜在於合併
    • 原地排序
    • 最壞情況爲O(n^2),但只要不是每次都是最壞,複雜度就不是n^2,具有韌性
  • 任何基於比較的排序,決策樹高度至少爲nlog(n)
  • 計數排序
    • 元素值範圍必須有限
    • 空間複雜度高
    • O(n)
  • 基數排序
    • 從最低位到最高位排序,每一位排序都採用穩定排序,如計數排序
    • 一位排序應該選擇log(n)個比特,使整體成本最低
  • 桶排序
    • 把n元素按值分到n個桶裏,每個桶內部進行插入排序,將各桶首位相連
    • 元素應該是均勻分佈
  • 快速次序選擇:求第K大的數
    • 使用快排的partition
    • 最差O(n^2),平均O(n)
  • 線性最差快速次序選擇
    • 將元素每5個一組,分別取中值。在n/5箇中值裏面找到中值,作爲partition的pivot
    • 爲什麼*不每3個一組?
    • 保證pivot左邊右邊至少3n/10個元素
    • 最差O(n)

第十一章 搜索與散列

  • 順序搜索
    • 在序列裏面如果搜索頻率從頭到尾指數遞減,則爲O(1)
  • 折半搜索
    • 對於有序序列,爲O(logn)
  • 常數搜索:散列搜索
    • 直接散列:非常簡單,不會發生碰撞,空間浪費大
    • 除法(模除法)散列
      • 元素對散列表大小m取模得到
      • m必須爲素數,否則造成不均勻散射。比如m包含因子d,而大部分元素對d餘數相等
      • m不能靠近2的冪。如m爲2的冪,散列結果將不依賴元素的所有位。靠近也不行,爲什麼
    • 乘法散列
      • h(k) = (A * k ) % 2^r >> (w - r),w爲計算機字寬,A爲2^(w-1)與2^w之間的一個奇數
      • 乘方取中法:乘方n次(常取n=2),取中間r位
  • 開放尋址散列:散列碰撞時縱深擴展,添加一個鏈表
    • 平均搜索時間爲O(1+a),a爲加載因子
  • 封閉尋址散列:散列碰撞時爲元素找到另一個位置
    • 找另一個位置的操作稱爲探尋
    • 線性探尋
      • h(k,i) = (h'(k) + i) % m,h'(k)爲家位
      • 向單方向尋找未被佔用的位置
      • 易出現頂級聚集
    • 非線性探尋
      • 平方探尋 h(k,i) = (h'(k) + c1 * i + c2 * i^2) % m 易出現次級聚集
    • 雙重散列探尋
      • 使用兩個散列函數h1、h2來構造新散列函數
      • h(k,i) = (h1(k) + i * h2(k) ) mod m
    • 僞隨機探尋
      • 使用僞隨機序列
      • 存在次級聚集
    • 不成功搜索的探尋次數期望爲1/(1-a)
    • 成功搜索探尋次數最多爲1 / a * ln( 1/(1-a))
    • 封閉散列不能刪除元素,可以放標記解決。如果插入相比搜索非常稀疏,則可以通過重新散列解決空位問題
  • 隨機化散列
    • 找到一組散列函數,每次隨機選擇一個不同的散列函數
    • 用於避免單個散列函數極端情況下聚集效應嚴重
    • 全域散列
      • 一組H個散列函數,將任意兩個不同的元素映射到同一位置的函數個數爲H/m
  • 完美散列
    • n個元素,構造m=O(n)大小的散列表,使搜索最壞達到O(1)
    • 採用雙層散列,第一層大小n,第二層每個表的大小爲落到第一層位置i上的元素個數的平方
    • 空間消耗爲O(n)

第十二章 最短路徑

  • 如果圖中有負環,則不存在最短路徑
  • 單源多點最短路徑
    • Dijkstra算法
      • 貪婪算法,要求不存在負路徑
      • 最優子結構:最短路徑裏的每一段都是兩點之間的最短路徑
      • 貪婪選擇屬性:路徑向外延伸的下一個節點就是離源點最近的節點
      • 每次選取離源點最近的節點,更新所有與此節點相鄰節點的距離
      • 時間複雜度爲O(V^2),採用堆實現,可以達到O(E log(V))。與Prim算法相同
    • Bellman-Ford算法
      • 可以應對負權重
      • 進行V-1輪降距,每次更新圖中所有邊
      • 複雜度爲O(VE)
    • BFS
      • 各邊權重相等的情況
      • O(V+E)
  • 多源多點最短路徑
    • Floyd-Warshall算法
      • 動態規劃算法
      • 子問題爲從i到j,中間結點只屬於集合1...k的最短路徑長度
      • c_ijk = min{c_ij(k-1), c_ik(k-1) + ckj(k-1)}|k
      • 複雜度O(n^3)
    • Jonhson算法
      • 等效變換爲無負權重的圖,使用Dijkstra算法
      • 添加一個節點s,到所有點路徑長度爲0,運行Bellman-Ford算法,對節點賦值
      • 對每個節點運行Dijkstra算法
      • 複雜度主要是Dijkstra算法運算,爲O(VE + V^2 log(V))
      • 若Bellman-Ford算法報告有負環存在,不能使用此方法

  
  

轉載請註明作者:Focustc,博客地址爲http://blog.csdn.net/caozhk,原文鏈接爲點擊打開

  
  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章