數據結構與算法 Big O 備忘錄與現實

不論今天的計算機技術變化,新技術的出現,全部都是來自數據結構與算法基礎。咱們須要溫故而知新。php

       算法、架構、策略、機器學習之間的關係。在過往和技術人員交流時,不少人對算法和架構之間的關係感到不可理解,算法是軟的,架構是硬的,難道算法和架構還有什麼關係不成?其實否則,算法和架構的關係很是緊密。在互聯網時代,咱們須要用算法處理的數據規模愈來愈大,要求的處理時間愈來愈短,單一計算機的處理能力是不可能知足需求的。而架構技術的發展,帶來了不少不一樣特色的分佈式計算平臺。算法爲了可以應用到這些分佈式計算平臺上,每每須要進化,例如:並行計算要求算法能夠拆分爲可並行計算的幾個獨立單位,但不少算法不具有這種可拆分特性,使得不能簡單經過分佈式計算來提升效率。這時候,爲了實現分佈式化的計算效果,須要將算法進行等效改寫,使得其具備獨立拆分性。另外一方面,算法的發展,也反過來會對計算架構提出新的要求。html

       對算法和策略的關係亦是,不過這兩個概念並不像算法和架構那樣好解釋。策略是解決具體問題的手段,而算法是解決一類問題的方法。解決一個具體問題,可能須要將問題分解爲一個或者多個算法,一塊兒做用來解決,也可能不須要算法。例如,對於個性化新聞,咱們可能有一個策略是:重大新聞須要及時展示給用戶;而實現的具體算法可能只包括「重大新聞挖掘算法」等。java

      機器學習是一類算法的統稱,在必定的數據集合上,利用機器學習的算法,自動獲得規律,來進行預測,機器學習領域常見的問題包括分類問題、迴歸問題等。而預測,尤爲是對用戶的偏好進行預測是推薦領域的核心問題之一,機器學習算法在解決此類問題上會發生很大的做用。node

  • 沒有最好的算法,只有合適的算法。推薦算法和產品需求、應用場景、數據密切相關,不要相信有什麼包打天下的算法;
  • 數據是基礎:數據充足並且質量高,簡單算法也能夠有不錯的效果;反之,則多好的算法也不可能有好的效果;
  • 木桶效應:算法策略要和用戶需求、功能展示密切配合;(注:木桶原理又稱短板理論,其核心內容爲「一隻木桶盛水的多少,並不取決於桶壁上最高的那塊木塊,而偏偏取決於桶壁上最短的那塊。」)
  • 通常而言,推薦算法都須要考慮是否能處理大數據,是否能大規模並行化。

 

正文linux

1、數據結構基礎 git

數組 github

定義 正則表達式

  • 按順序連續存儲數據元素,一般索引從0開始
  • 以集合論中的元組爲基礎
  • 數組是最古老,最經常使用的數據結構

知識要點 算法

  • 索引最優;不利於查找、插入和刪除(除非在數組最末進行)
  • 最基礎的是線性數組或一維數組
    數組長度固定,意味着聲明數組時應指明長度
  • 動態數組與一維數組相似,但爲額外添加的元素預留了空間
    若是動態數組已滿,則把每一元素複製到更大的數組中
  • 相似網格或嵌套數組,二維數組有 x 和 y 索引

時間複雜度 chrome

  • O(1)索引:一維數組:O(1),動態數組:O(1)
  • O(n)查找:一維數組:O(n),動態數組:O(n)
  • O(log n)最優查找:一維數組:O(log n),動態數組:O(log n)
  • O(n)插入:一維數組:n/a,動態數組:O(n)

鏈表

定義

  • 結點存儲數據,並指向下一結點
    最基礎的結點包含一個數據和一個指針(指向另外一結點)
    • 鏈表靠結點中指向下一結點的指針鏈接成鏈

要點

  • 爲優化插入和刪除而設計,但不利於索引和查找
  • 雙向鏈表包含指向前一結點的指針
  • 循環鏈表是一種終端結點指針域指向頭結點的簡單鏈表
  • 堆棧一般由鏈表實現,不過也能夠利用數組實現
    堆棧是「後進先出」(LIFO)的數據結構
    • 由鏈表實現時,只有頭結點處能夠進行插入或刪除操做
  • 一樣地,隊列也能夠經過鏈表或數組實現
    隊列是「先進先出」(FIFO)的數據結構
    • 由雙向鏈表實現時,只能在頭部刪除,在末端插入

時間複雜度

  • O(n)索引:鏈表:O(n)
  • O(n)查找:鏈表:O(n)
  • Linked Lists: O(n)最優查找:鏈表:O(n)
  • O(1)插入:鏈表:O(1)

哈希表或哈希圖

定義

  • 經過鍵值對進行儲存
  • 哈希函數接受一個關鍵字,並返回該關鍵字惟一對應的輸出值
    這一過程稱爲散列(hashing),是輸入與輸出一一對應的概念
    • 哈希函數爲該數據返回在內存中惟一的存儲地址

要點

  • 爲查找、插入和刪除而設計
  • 哈希衝突是指哈希函數對兩個不一樣的數據項產生了相同的輸出值
    全部的哈希函數都存在這個問題
    • 用一個很是大的哈希表,能夠有效緩解這一問題
    • 哈希表對於關聯數組和數據庫檢索十分重要

時間複雜度

  • O(1)索引:哈希表:O(1)
  • O(1)查找:哈希表:O(1)
  • O(1)插入:哈希表:O(1)

二叉樹

定義

  • 一種樹形的數據結構,每一結點最多有兩個子樹
    • 子結點又分爲左子結點和右子結點

要點

  • 爲優化查找和排序而設計
  • 退化樹是一種不平衡的樹,若是徹底只有一邊,其本質就是一個鏈表
  • 相比於其餘數據結構,二叉樹較爲容易實現
  • 可用於實現二叉查找樹
    • 二叉樹利用可比較的鍵值來肯定子結點的方向
    • 左子樹有比雙親結點更小的鍵值
    • 右子樹有比雙親結點更大的鍵值
    • 重複的結點可省略
    • 因爲上述緣由,二叉查找樹一般被用做一種數據結構,而不是二叉樹

時間複雜度

  • 索引:二叉查找樹:O(log n)
  • 查找:二叉查找樹:O(log n)
  • 插入:二叉查找樹:O(log n)

2、搜索基礎

廣度優先搜索

定義

  • 一種在樹(或圖)中進行搜索的算法,從根結點開始,優先按照樹的層次進行搜索
    • 搜索同一層中的各結點,一般從左往右進行
    • 進行搜索時,同時追蹤當前層中結點的子結點
    • 當前一層搜索完畢後,轉入遍歷下一層中最左邊的結點
    • 最下層最右端是最末結點(即該結點深度最大,且在當前層次的最右端)

要點

  • 當樹的寬度大於深度時,該搜索算法較優
  • 進行樹的遍歷時,使用隊列存儲樹的信息
    • 緣由是:使用隊列比深度優先搜索更爲內存密集
    • 因爲須要存儲指針,隊列須要佔用更多內存

時間複雜度

  • O(|E| + |V|)查找:廣度優先搜索:O(|E| + |V|)
  • E 是邊的數目
  • V 是頂點的數目

深度優先搜索

定義

  • 一種在樹(或圖)中進行搜索的算法,從根結點開始,優先按照樹的深度進行搜索
    • 從左邊開始一直往下遍歷樹的結點,直到不能繼續這一操做
    • 一旦到達某一分支的最末端,將返回上一結點並遍歷該分支的右子結點,若是能夠將從左往右遍歷子結點
    • 當前這一分支搜索完畢後,轉入根節點的右子結點,而後不斷遍歷左子節點,直到到達最底端
    • 最右的結點是最末結點(即全部祖先中最右的結點)

要點

  • 當樹的深度大於寬度時,該搜索算法較優
  • 利用堆棧將結點壓棧
    • 由於堆棧是「後進先出」的數據結構,因此無需跟蹤結點的指針。與廣度優先搜索相比,它對內存的要求不高。
    • 一旦不能向左繼續遍歷,則對棧進行操做

時間複雜度

  • O(|E| + |V|)查找:深度優先搜索:O(|E| + |V|)
  • E 是邊的數目
  • V 是結點的數目

廣度優先搜索 VS. 深度優先搜索

  • 這一問題最簡單的回答就是,選取何種算法取決於樹的大小和形態
    • 就寬度而言,較淺的樹適用廣度優先搜索
    • 就深度而言,較窄的樹適用深度優先搜索

細微的區別

  • 因爲廣度優先搜索(BFS)使用隊列來存儲結點的信息和它的子結點,因此須要用到的內存可能超過當前計算機可提供的內存(不過其實你沒必要擔憂這一點)
  • 若是要在某一深度很大的樹中使用深度優先搜索(DFS),其實在搜索中大可沒必要走徹底部深度。可在 xkcd 上查看更多相關信息。
  • 廣度優先搜索趨於一種循環算法。
  • 深度優先搜索趨於一種遞歸算法

3、高效排序基礎

歸併排序

定義

  • 一種基於比較的排序算法
    • 將整個數據集劃分紅至多有兩個數的分組
    • 依次比較每一個數字,將最小的數移動到每對數的左邊
    • 一旦全部的數對都完成排序,則開始比較最左兩個數對中的最左元素,造成一個含有四個數的有序集合,其中最小數在最左邊,最大數在最右邊
    • 重複上述過程,直到歸併成只有一個數據集

要點

  • 這是最基礎的排序算法之一
  • 必須理解:首先將全部數據劃分紅儘量小的集合,再做比較

時間複雜度

  • O(n)最好的狀況:歸併排序:O(n)
  • 平均狀況:歸併排序:O(n log n)
  • 最壞的狀況:歸併排序:O(n log n)

快速排序

定義

  • 一種基於比較的排序算法
    • 經過選取平均數將整個數據集劃分紅兩部分,並把全部小於平均數的元素移動到平均數左邊
    • 在左半部分重複上述操做,直到左邊部分的排序完成後,對右邊部分執行相同的操做
  • 計算機體系結構支持快速排序過程

要點

  • 儘管快速排序與許多其餘排序算法有相同的時間複雜度(有時會更差),但一般比其餘排序算法執行得更快,例如歸併排序。
  • 必須理解:不斷經過平均數將數據集對半劃分,直到全部的數據都完成排序

時間複雜度

  • O(n)最好的狀況:歸併排序:O(n)
  • O(n log n)平均狀況:歸併排序:O(n log n)
  • 最壞的狀況:歸併排序:O(n2)

冒泡排序

定義

  • 一種基於比較的排序算法
    • 從左往右重複對數字進行兩兩比較,把較小的數移到左邊
    • 重複上述步驟,直到再也不把元素左移

要點

  • 儘管這一算法很容易實現,倒是這三種排序方法中效率最低的
  • 必須理解:每次向右移動一位,比較兩個元素,並把較小的數左移

時間複雜度

  • O(n)最好的狀況:歸併排序:O(n)
  • O(n2)平均狀況:歸併排序: O(n2)
  • O(n2)最壞的狀況:歸併排序: O(n2)

歸併排序 VS. 快速排序

  • 在實踐中,快速排序執行速率更快
  • 歸併排序首先將集合劃分紅最小的分組,在對分組進行排序的同時,遞增地對分組進行合併
  • 快速排序不斷地經過平均數劃分集合,直到集合遞歸地有序

4、算法類型基礎

遞歸算法

定義

  • 在定義過程當中調用其自己的算法
    • 遞歸事件:用於觸發遞歸的條件語句
    • 基本事件:用於結束遞歸的條件語句

要點

  • 堆棧級過深和棧溢出
    • 若是在遞歸算法中見到上述兩種狀況中的任一個,那就糟糕了
    • 那就意味着由於算法錯誤,或者問題規模太過龐大致使問題解決前 RAM 已耗盡,從而基本事件從未被觸發
    • 必須理解:不論基本事件是否被觸發,它在遞歸中都不可或缺
    • 一般用於深度優先搜索

迭代算法

定義

  • 一種被重複調用有限次數的算法,每次調用都是一次迭代
    • 一般用於數據集中遞增移動

要點

  • 一般迭代的形式爲循環、for、while和until語句
  • 把迭代看做是在集合中依次遍歷每一個元素
  • 一般用於數組的遍歷

遞歸 VS. 迭代

  • 因爲遞歸和迭代能夠相互實現,二者之間的區別很難清晰地界定。但必須知道:
    • 一般遞歸的表意性更強,更易於實現
    • 迭代佔用的內存更少
  • (i.e. Haskell)函數式語言趨向於使用遞歸(如 Haskell 語言)
  • 命令式語言趨向於使用迭代(如 Ruby 語言)
  • 點擊 Stack Overflow post 瞭解更多詳情

遍歷數組的僞代碼(這就是爲何使用迭代的緣由)

Recursion | Iteration

----------------------------------|----------------------------------

recursive method (array, n) | iterative method (array)

if array[n] is not nil | for n from 0 to size of array

print array[n] | print(array[n])

recursive method(array, n+1) |

else |

exit loop

貪婪算法

定義

  • 一種算法,在執行的同時只選擇知足某一條件的信息
  • 一般包含5個部分,摘自維基百科:
    • 候選集,從該集合中可得出解決方案
    • 選擇函數,該函數選取要加入解決方案中的最優候選項
    • 可行性函數,該函數用於決策某一候選項是否有助於解決方案
    • 目標函數,該函數爲解決方案或部分解賦值
    • 解決方案函數,該函數將指明完整的解決方案

要點

  • 用於找到預約問題的最優解
  • 一般用於只有少部分元素能知足預期結果的數據集合
  • 一般貪婪算法可幫助一個算法下降時間 複雜度

僞代碼:用貪婪算法找到數組中任意兩個數字間的最大差值

greedy algorithm (array)

var largest difference = 0

var new difference = find next difference (array[n], array[n+1])

largest difference = new difference if new difference is > largest difference

repeat above two steps until all differences have been found

return largest difference

這一算法無需比較全部數字兩兩之間的差值,省略了一次完整迭代。

如下是Big O 覈對表

Legend

Excellent

Good

Fair

Bad

Horrible

Data Structure Operations

Data Structure

Time Complexity

 

 

 

 

 

 

 

Space Complexity

 

Average

 

 

 

Worst

 

 

 

Worst

 

Access

Search

Insertion

Deletion

Access

Search

Insertion

Deletion

 

Array

O(1)

O(n)

O(n)

O(n)

O(1)

O(n)

O(n)

O(n)

O(n)

Stack

O(n)

O(n)

O(1)

O(1)

O(n)

O(n)

O(1)

O(1)

O(n)

Singly-Linked List

O(n)

O(n)

O(1)

O(1)

O(n)

O(n)

O(1)

O(1)

O(n)

Doubly-Linked List

O(n)

O(n)

O(1)

O(1)

O(n)

O(n)

O(1)

O(1)

O(n)

Skip List

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(n)

O(n)

O(n)

O(n)

O(n log(n))

Hash Table

-

O(1)

O(1)

O(1)

-

O(n)

O(n)

O(n)

O(n)

Binary Search Tree

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(n)

O(n)

O(n)

O(n)

O(n)

Cartesian Tree

-

O(log(n))

O(log(n))

O(log(n))

-

O(n)

O(n)

O(n)

O(n)

B-Tree

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(n)

Red-Black Tree

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(n)

Splay Tree

-

O(log(n))

O(log(n))

O(log(n))

-

O(log(n))

O(log(n))

O(log(n))

O(n)

AVL Tree

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(n)

Array Sorting Algorithms

Algorithm

Time Complexity

 

 

Space Complexity

 

Best

Average

Worst

Worst

Quicksort

O(n log(n))

O(n log(n))

O(n^2)

O(log(n))

Mergesort

O(n log(n))

O(n log(n))

O(n log(n))

O(n)

Timsort

O(n)

O(n log(n))

O(n log(n))

O(n)

Heapsort

O(n log(n))

O(n log(n))

O(n log(n))

O(1)

Bubble Sort

O(n)

O(n^2)

O(n^2)

O(1)

Insertion Sort

O(n)

O(n^2)

O(n^2)

O(1)

Selection Sort

O(n^2)

O(n^2)

O(n^2)

O(1)

Shell Sort

O(n)

O((nlog(n))^2)

O((nlog(n))^2)

O(1)

Bucket Sort

O(n+k)

O(n+k)

O(n^2)

O(n)

Radix Sort

O(nk)

O(nk)

O(nk)

O(n+k)

Graph Operations

Node / Edge Management

Storage

Add Vertex

Add Edge

Remove Vertex

Remove Edge

Query

Adjacency list

O(|V|+|E|)

O(1)

O(1)

O(|V| + |E|)

O(|E|)

O(|V|)

Incidence list

O(|V|+|E|)

O(1)

O(1)

O(|E|)

O(|E|)

O(|E|)

Adjacency matrix

O(|V|^2)

O(|V|^2)

O(1)

O(|V|^2)

O(1)

O(1)

Incidence matrix

O(|V| |E|)

O(|V| |E|)

O(|V| |E|)

O(|V| |E|)

O(|V| |E|)

O(|E|)

Heap Operations

Type

Time Complexity

 

 

 

 

 

 

 

Heapify

Find Max

Extract Max

Increase Key

Insert

Delete

Merge

Linked List (sorted)

-

O(1)

O(1)

O(n)

O(n)

O(1)

O(m+n)

Linked List (unsorted)

-

O(n)

O(n)

O(1)

O(1)

O(1)

O(1)

Binary Heap

O(n)

O(1)

O(log(n))

O(log(n))

O(log(n))

O(log(n))

O(m+n)

Binomial Heap

-

O(1)

O(log(n))

O(log(n))

O(1)

O(log(n))

O(log(n))

Fibonacci Heap

-

O(1)

O(log(n))

O(1)

O(1)

O(log(n))

O(1)

Big-O Complexity Chart

 

clip_image001[4]

計算機科學中最重要的32個算法

  1. A* 搜索算法——圖形搜索算法,從給定起點到給定終點計算出路徑。其中使用了一種啓發式的估算,爲每一個節點估算經過該節點的最佳路徑,並以之爲各個地點排定次序。算法以獲得的次序訪問這些節點。所以,A*搜索算法是最佳優先搜索的範例。
  2. 集束搜索(又名定向搜索,Beam Search)——最佳優先搜索算法的優化。使用啓發式函數評估它檢查的每一個節點的能力。不過,集束搜索只能在每一個深度中發現最前面的m個最符合條件的節點,m是固定數字——集束的寬度。
  3. 二分查找(Binary Search)——在線性數組中找特定值的算法,每一個步驟去掉一半不符合要求的數據。
  4. 分支界定算法(Branch and Bound)——在多種最優化問題中尋找特定最優化解決方案的算法,特別是針對離散、組合的最優化。
  5. Buchberger算法——一種數學算法,可將其視爲針對單變量最大公約數求解的歐幾里得算法和線性系統中高斯消元法的泛化。
  6. 數據壓縮——採起特定編碼方案,使用更少的字節數(或是其餘信息承載單元)對信息編碼的過程,又叫來源編碼。
  7. Diffie-Hellman密鑰交換算法——一種加密協議,容許雙方在事先不瞭解對方的狀況下,在不安全的通訊信道中,共同創建共享密鑰。該密鑰之後可與一個對稱密碼一塊兒,加密後續通信。
  8. Dijkstra算法——針對沒有負值權重邊的有向圖,計算其中的單一塊兒點最短算法。
  9. 離散微分算法(Discrete differentiation)
  10. 動態規劃算法(Dynamic Programming)——展現互相覆蓋的子問題和最優子架構算法
  11. 歐幾里得算法(Euclidean algorithm)——計算兩個整數的最大公約數。最古老的算法之一,出如今公元前300前歐幾里得的《幾何本來》。
  12. 指望-最大算法(Expectation-maximization algorithm,又名EM-Training)——在統計計算中,指望-最大算法在機率模型中尋找可能性最大的參數估算值,其中模型依賴於未發現的潛在變量。EM在兩個步驟中交替計算,第一步是計算指望,利用對隱藏變量的現有估計值,計算其最大可能估計值;第二步是最大化,最大化在第一步上求得的最大可能值來計算參數的值。
  13. 快速傅里葉變換(Fast Fourier transform,FFT)——計算離散的傅里葉變換(DFT)及其反轉。該算法應用範圍很廣,從數字信號處理到解決偏微分方程,到快速計算大整數乘積。
  14. 梯度降低(Gradient descent)——一種數學上的最優化算法。
  15. 哈希算法(Hashing)
  16. 堆排序(Heaps)
  17. Karatsuba乘法——須要完成上千位整數的乘法的系統中使用,好比計算機代數系統和大數程序庫,若是使用長乘法,速度太慢。該算法發現於1962年。
  18. LLL算法(Lenstra-Lenstra-Lovasz lattice reduction)——以格規約(lattice)基數爲輸入,輸出短正交向量基數。LLL算法在如下公共密鑰加密方法中有大量使用:揹包加密系統(knapsack)、有特定設置的RSA加密等等。
  19. 最大流量算法(Maximum flow)——該算法試圖從一個流量網絡中找到最大的流。它優點被定義爲找到這樣一個流的值。最大流問題能夠看做更復雜的網絡流問題的特定狀況。最大流與網絡中的界面有關,這就是最大流-最小截定理(Max-flow min-cut theorem)。Ford-Fulkerson 能找到一個流網絡中的最大流。
  20. 合併排序(Merge Sort)
  21. 牛頓法(Newton's method)——求非線性方程(組)零點的一種重要的迭代法。
  22. Q-learning學習算法——這是一種經過學習動做值函數(action-value function)完成的強化學習算法,函數採起在給定狀態的給定動做,並計算出指望的效用價值,在此後遵循固定的策略。Q-leanring的優點是,在不須要環境模型的狀況下,能夠對比可採納行動的指望效用。
  23. 兩次篩法(Quadratic Sieve)——現代整數因子分解算法,在實踐中,是目前已知第二快的此類算法(僅次於數域篩法Number Field Sieve)。對於110位如下的十位整數,它還是最快的,並且都認爲它比數域篩法更簡單。
  24. RANSAC——是「RANdom SAmple Consensus」的縮寫。該算法根據一系列觀察獲得的數據,數據中包含異常值,估算一個數學模型的參數值。其基本假設是:數據包含非異化值,也就是可以經過某些模型參數解釋的值,異化值就是那些不符合模型的數據點。
  25. RSA——公鑰加密算法。首個適用於以簽名做爲加密的算法。RSA在電商行業中仍大規模使用,你們也相信它有足夠安全長度的公鑰。
  26. Schönhage-Strassen算法——在數學中,Schönhage-Strassen算法是用來完成大整數的乘法的快速漸近算法。其算法複雜度爲:O(N log(N) log(log(N))),該算法使用了傅里葉變換。
  27. 單純型算法(Simplex Algorithm)——在數學的優化理論中,單純型算法是經常使用的技術,用來找到線性規劃問題的數值解。線性規劃問題包括在一組實變量上的一系列線性不等式組,以及一個等待最大化(或最小化)的固定線性函數。
  28. 奇異值分解(Singular value decomposition,簡稱SVD)——在線性代數中,SVD是重要的實數或複數矩陣的分解方法,在信號處理和統計中有多種應用,好比計算矩陣的僞逆矩陣(以求解最小二乘法問題)、解決超定線性系統(overdetermined linear systems)、矩陣逼近、數值天氣預報等等。
  29. 求解線性方程組(Solving a system of linear equations)——線性方程組是數學中最古老的問題,它們有不少應用,好比在數字信號處理、線性規劃中的估算和預測、數值分析中的非線性問題逼近等等。求解線性方程組,可使用高斯—約當消去法(Gauss-Jordan elimination),或是柯列斯基分解( Cholesky decomposition)。
  30. Strukturtensor算法——應用於模式識別領域,爲全部像素找出一種計算方法,看看該像素是否處於同質區域( homogenous region),看看它是否屬於邊緣,仍是是一個頂點。
  31. 合併查找算法(Union-find)——給定一組元素,該算法經常用來把這些元素分爲多個分離的、彼此不重合的組。不相交集(disjoint-set)的數據結構能夠跟蹤這樣的切分方法。合併查找算法能夠在此種數據結構上完成兩個有用的操做:
      • 查找:判斷某特定元素屬於哪一個組。
      • 合併:聯合或合併兩個組爲一個組。
  32. 維特比算法(Viterbi algorithm)——尋找隱藏狀態最有可能序列的動態規劃算法,這種序列被稱爲維特比路徑,其結果是一系列能夠觀察到的事件,特別是在隱藏的Markov模型中。

現實中算法

Linux內核中的基本數據結構和算法

  1. 鏈表雙向鏈表無鎖鏈表
  2. B+ 樹,代碼中的註釋將會告訴你一些教科書中不能學到的內容:

    這是一個簡單的B+樹實現,我寫它的目的是做爲練習,並以此瞭解B+樹的工做原理。結果該實現發揮了它的實用價值。

    ...

    一個不常常在教科書中說起的技巧:最小值應該放在右側,而不是左側。一個節點內全部被使用的槽位應該在左側,沒有使用的節點應該爲NUL,大部分的操做只遍歷一次全部的槽位,在第一個NUL處終止。

  3. 帶權重的有序列表用於互斥鎖驅動等;

  4. 紅黑樹用於調度、虛擬內存管理、跟蹤文件描述符和目錄條目等;
  5. 區間樹
  6. Radix樹,用於內存管理、NFS相關查找和網絡相關的功能;

    radix樹的一個常見的用法是保存頁面結構體的指針;

  7. 優先級堆,文字上的描述,主要是在教科書中實現,用於control group系統;

    包含指針的只容許簡單插入的靜態大小優先級堆,基於CLR(算法導論)第七章

  8. 哈希函數,引用Knuth和他的一篇論文:

    Knuth建議選擇與機器字長所能表達的最大整數約成黃金比例的素數來作乘法散列,Chuck Lever 證明了這個技術的有效性;

    http://www.citi.umich.edu/techreports/reports/citi-tr-00-1.pdf

    這些選擇的素數是位稀疏的,也就是說對他們的操做可使用位移和加法來替換機器中很慢的乘法操做;

  9. 有些代碼,好比這個驅動,他們是本身實現的哈希函數

  10. 哈希表,用於實現索引節點文件系統完整性檢查等;
  11. 位數組,用於處理flags、中斷等,在Knuth第四卷中有對其特性的描述;
  12. Semaphoresspin locks
  13. 二叉樹搜索用於中斷處理登記緩存查找等;
  14. 使用B-樹進行二叉樹查找
  15. 深度優先搜索和他的變體被應用於目錄配置

    在命名空間樹中執行一個修改過的深度優先算法,開始(和終止於)start_handle所肯定的節點。當與參數匹配的節點被發現之後,回調函數將會被調用。若是回調函數返回一個非空的值,搜索將會當即終止,這個值將會回傳給調用函數;

  16. 廣度優先搜索用於在運行時檢查鎖的正確性;
  17. 鏈表上的合併排序用於垃圾回收文件系統管理等;
  18. 在某個驅動程序的庫函數裏,冒泡排序竟然也被實現了
  19. Knuth-Morris-Pratt 字符串匹配

    Knuth、Morris和 Pratt [1]實現了一個線性時間複雜度字符串匹配算法。該算法徹底規避了對轉換函數DELTA的顯式計算。其匹配時間爲O(n)(其中n是文本長度),只使用一個輔助函數PI[1...m](其中m是模式的長度),模式的預處理時間是O(m)。PI這個數組容許DELTA函數在須要時能迅速運行。大致上,對任意狀態q=0,1,...,m和任意SIGMA中的字符"a",PI["q"]保存了獨立於"a"的信息,並用於計算DELTA("q", "a")。因爲PI這個數組只包含m個條目,而DELTA包含O(m|SIGMA|)個條目,咱們經過計算PI進而在預處理時間保存|SIGMA|的係數,而非計算DELTA。

    [1] Cormen, Leiserson, Rivest, Stein Introdcution to Algorithms, 2nd Edition, MIT Press

    [2] See finite automation theory

  20. Boyer-Moore模式匹配,以下是引用和對其餘算法的使用建議;

    Boyer-Moore字符串匹配算法:

    [1] A Fast String Searching Algorithm, R.S. Boyer and Moore. Communications of the Association for Computing Machinery, 20(10), 1977, pp. 762-772. http://www.cs.utexas.edu/users/moore/publications/fstrpos.pdf

    [2] Handbook of Exact String Matching Algorithms, Thierry Lecroq, 2004 http://www-igm.univ-mlv.fr/~lecroq/string/string.pdf

    注意:因爲Boyer-Moore(BM)自右向左作匹配,有一種可能性是一個匹配分佈在不一樣的塊中,這種狀況下是不能找到任何匹配的。

    若是你想確保這樣的事情不會發生,使用Knuth-Pratt-Morris(KMP)算法來替代。也就是說,根據你的設置選擇合適的字符串查找算法。

    若是你使用文本搜索架構來過濾、網絡入侵檢測(NIDS)或者任何安全爲目的,那麼選擇KMP。若是你關乎性能,好比你在分類數據包,並應用服務質量(QoS)策略,而且你不介意可能須要在分佈在多個片斷中匹配,而後就選擇BM。

Chromium 瀏覽器中的數據結構和算法

  1. 伸展樹

    此樹會被分配策略參數化,這個策略負責在C的自由存儲空間和區域中分配列表,參見zone.h

  2. Demo中使用了Voronoi
  3. 基於Bresenham算法的標籤管理

同時,代碼中還包含了一些第三方的算法和數據結構,例如:

  1. 二叉樹
  2. 紅黑樹
  3. AVL樹
  4. 用於壓縮的Rabin-Karp字符串匹配
  5. 計算自動機的後綴
  6. 蘋果實現的布隆過濾器
  7. 布氏算法

編程語言類庫

  1. C++ STL,包含的有列表、堆、棧、向量、排序、搜索和堆操做算法
  2. Java API 很是普遍,包含的太多
  3. Boost C++ 類庫,包含了諸如Boyer-Moore和Knuth-Morris-Pratt字符串匹配算法等;

分配和調度算法

  1. 最近最少使用算法有多種實現方式,在Linux內核中是基於列表實現的;
  2. 其餘可能須要瞭解的是先入先出、最不經常使用和輪詢;
  3. VAX、VMS系統中大量使用FIFO的變體;
  4. Richard Carr時鐘算法被用於Linux中頁面幀替換;
  5. Intel i860處理器中使用了隨機替換策略;
  6. 自適應緩存替換被用於一些IBM的存儲控制中,因爲專利緣由在PostgreSQL只有簡單的應用;
  7. Knuth在TAOCP第一卷中提到的夥伴內存分配算法被用於Linux內核中,FreeBSD和Facebook都在使用jemalloc併發分配器;

*nix系統中的核心組件

  1. grep和awk都實現了使用Thompson-McNaughton-Yamada構建算法實現從正則表達式中建立NFA
  2. tsort實現了拓撲排序
  3. fgrep實現了Aho-Corasick 字符串匹配算法
  4. GNU grep,據做者Mike Haertel所說,實現了Boyer-Moore算法
  5. Unix中的crypt(1)實現了啞謎機(Enigma Machine)中的加密算法的變種;
  6. Doug Mcllroy基於和James合做的原型實現的Unix diff,比用來計算Levenshtein距離的標準動態規劃算法更好,Linux版本被用來計算最短編輯距離;

加密算法

  1. Merkle樹,尤爲是Tiger Tree Hash的變種,用於點對點的程序,例如GTK GnutellaLimeWire;
  2. MD5用於爲軟件包提供校驗碼,還用於*nix系統(Linux實現)中的完整性校驗,同時他還支持Windows和OS X系統;
  3. OpenSSL實現了須要加密算法,諸如AES,Blowfish,DES,SHA-1,SHA-2,RSA,DES等;

編譯器

  1. yacc和bison實現了LALR解析器
  2. 支配算法用於基於SSA形式的最優化編譯器;
  3. lex和flex將正則表達式編譯爲NFA;

壓縮和圖片處理

  1. 爲GIF圖片格式而出現的Lempel-Zivsraf算法在圖片處理程序中常常被應用,從一個簡單的*nix組件轉化爲一個複雜的程序;

  2. 運行長度編碼被用於生成PCX文件(用於Paintbrush這個程序中),壓縮BMP文件和TIFF文件;

  3. 小波壓縮(Wavelet壓縮)是JPEG 2000的基礎,因此全部生成JPEG 2000文件的數碼相機都是實現了這個算法;

  4. Reed-Solomon糾錯用於Linux內核、CD驅動、條形碼讀取,而且結合卷積從航行團隊進行圖片傳輸;

衝突驅動條款學習算法(Conflict Driven Clause Learning)

自2000年以來,在工業標準中的SAT(布爾知足性問題)求解器的運行時間每一年都在成倍減小。這一發展的一個很是重要的緣由是衝突驅動條款學習算法(Conflict Driven Clause Learning)的使用,它結合了Davis Logemann和Loveland的約束編程和人工智能研究技術的原始論文中關於布爾約束傳播的算法。具體來講,工業建模中SAT被認爲是一個簡單的問題(見討論)。對我來講,這是近代最偉大的成功故事之一,由於它結合了先進的算法、巧妙的設計思路、實驗反饋,並以一致的共同努力來解決這個問題。Malik和Zhang的CACM論文是一個很好的閱讀材料。許多大學都在教授這個算法,但一般是在邏輯或形式化方法的課程中。

 

 


但願對您企業應用開發與企業信息化有幫助。 其它您可能感興趣的文章:

視覺直觀感覺 7 種經常使用的排序算法

匈牙利 Sapientia 大學的 6 種排序算法舞蹈視頻

視頻:6 分鐘演示 15 種排序算法

SORTING:可視化展現排序算法的原理,支持單步查看

VisuAlgo:經過動畫學習算法和數據結構

軟件開發的專業化
IT基礎架構規劃方案一(網絡系統規劃)
IT基礎架構規劃方案二(計算機系統與機房規劃規劃) 
IT基礎架構規劃方案三(IT基礎軟件和系統規劃)
企業應用之性能實時度量系統演變
雲計算參考架構幾例
智能移動導遊解決方案簡介
人力資源管理系統的演化

若有想了解更多軟件研發 , 系統 IT集成 , 企業信息化 等資訊,請關注個人微信訂閱號:

MegadotnetMicroMsg_thumb1_thumb1_thu[1]


做者:Petter Liu
出處:http://www.cnblogs.com/wintersun/
本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。
該文章也同時發佈在個人獨立博客中-Petter Liu Blog

相關文章
相關標籤/搜索