数据结构与算法 Big O 备忘录与现实
不論今天的計算機技術(shù)變化,新技術(shù)的出現(xiàn),所有都是來自數(shù)據(jù)結(jié)構(gòu)與算法基礎(chǔ)。我們需要溫故而知新。
?????? 算法、架構(gòu)、策略、機器學(xué)習(xí)之間的關(guān)系。在過往和技術(shù)人員交流時,很多人對算法和架構(gòu)之間的關(guān)系感到不可理解,算法是軟的,架構(gòu)是硬的,難道算法和架構(gòu)還有什么關(guān)系不成?其實不然,算法和架構(gòu)的關(guān)系非常緊密。在互聯(lián)網(wǎng)時代,我們需要用算法處理的數(shù)據(jù)規(guī)模越來越大,要求的處理時間越來越短,單一計算機的處理能力是不可能滿足需求的。而架構(gòu)技術(shù)的發(fā)展,帶來了很多不同特點的分布式計算平臺。算法為了能夠應(yīng)用到這些分布式計算平臺上,往往需要進化,例如:并行計算要求算法可以拆分為可并行計算的幾個獨立單位,但很多算法不具備這種可拆分特性,使得不能簡單通過分布式計算來提高效率。這時候,為了實現(xiàn)分布式化的計算效果,需要將算法進行等效改寫,使得其具有獨立拆分性。另一方面,算法的發(fā)展,也反過來會對計算架構(gòu)提出新的要求。
?????? 對算法和策略的關(guān)系亦是,不過這兩個概念并不像算法和架構(gòu)那樣好解釋。策略是解決具體問題的手段,而算法是解決一類問題的方法。解決一個具體問題,可能需要將問題分解為一個或者多個算法,一起作用來解決,也可能不需要算法。例如,對于個性化新聞,我們可能有一個策略是:重大新聞需要及時展現(xiàn)給用戶;而實現(xiàn)的具體算法可能只包括“重大新聞挖掘算法”等。
????? 機器學(xué)習(xí)是一類算法的統(tǒng)稱,在一定的數(shù)據(jù)集合上,利用機器學(xué)習(xí)的算法,自動得到規(guī)律,來進行預(yù)測,機器學(xué)習(xí)領(lǐng)域常見的問題包括分類問題、回歸問題等。而預(yù)測,尤其是對用戶的偏好進行預(yù)測是推薦領(lǐng)域的核心問題之一,機器學(xué)習(xí)算法在解決此類問題上會發(fā)生很大的作用。
- 沒有最好的算法,只有合適的算法。推薦算法和產(chǎn)品需求、應(yīng)用場景、數(shù)據(jù)密切相關(guān),不要相信有什么包打天下的算法;
- 數(shù)據(jù)是基礎(chǔ):數(shù)據(jù)充足而且質(zhì)量高,簡單算法也可以有不錯的效果;反之,則多好的算法也不可能有好的效果;
- 木桶效應(yīng):算法策略要和用戶需求、功能展現(xiàn)密切配合;(注:木桶原理又稱短板理論,其核心內(nèi)容為“一只木桶盛水的多少,并不取決于桶壁上最高的那塊木塊,而恰恰取決于桶壁上最短的那塊。”)
- 一般而言,推薦算法都需要考慮是否能處理大數(shù)據(jù),是否能大規(guī)模并行化。
?
正文
一、數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)
數(shù)組
定義
- 按順序連續(xù)存儲數(shù)據(jù)元素,通常索引從0開始
- 以集合論中的元組為基礎(chǔ)
- 數(shù)組是最古老,最常用的數(shù)據(jù)結(jié)構(gòu)
知識要點
- 索引最優(yōu);不利于查找、插入和刪除(除非在數(shù)組最末進行)
- 最基礎(chǔ)的是線性數(shù)組或一維數(shù)組
數(shù)組長度固定,意味著聲明數(shù)組時應(yīng)指明長度 - 動態(tài)數(shù)組與一維數(shù)組類似,但為額外添加的元素預(yù)留了空間
如果動態(tài)數(shù)組已滿,則把每一元素復(fù)制到更大的數(shù)組中 - 類似網(wǎng)格或嵌套數(shù)組,二維數(shù)組有 x 和 y 索引
時間復(fù)雜度
- O(1)索引:一維數(shù)組:O(1),動態(tài)數(shù)組:O(1)
- O(n)查找:一維數(shù)組:O(n),動態(tài)數(shù)組:O(n)
- O(log n)最優(yōu)查找:一維數(shù)組:O(log n),動態(tài)數(shù)組:O(log n)
- O(n)插入:一維數(shù)組:n/a,動態(tài)數(shù)組:O(n)
鏈表
定義
- 結(jié)點存儲數(shù)據(jù),并指向下一結(jié)點
最基礎(chǔ)的結(jié)點包含一個數(shù)據(jù)和一個指針(指向另一結(jié)點)- 鏈表靠結(jié)點中指向下一結(jié)點的指針連接成鏈
要點
- 為優(yōu)化插入和刪除而設(shè)計,但不利于索引和查找
- 雙向鏈表包含指向前一結(jié)點的指針
- 循環(huán)鏈表是一種終端結(jié)點指針域指向頭結(jié)點的簡單鏈表
- 堆棧通常由鏈表實現(xiàn),不過也可以利用數(shù)組實現(xiàn)
堆棧是“后進先出”(LIFO)的數(shù)據(jù)結(jié)構(gòu)- 由鏈表實現(xiàn)時,只有頭結(jié)點處可以進行插入或刪除操作
- 同樣地,隊列也可以通過鏈表或數(shù)組實現(xiàn)
隊列是“先進先出”(FIFO)的數(shù)據(jù)結(jié)構(gòu)- 由雙向鏈表實現(xiàn)時,只能在頭部刪除,在末端插入
時間復(fù)雜度
- O(n)索引:鏈表:O(n)
- O(n)查找:鏈表:O(n)
- Linked Lists: O(n)最優(yōu)查找:鏈表:O(n)
- O(1)插入:鏈表:O(1)
哈希表或哈希圖
定義
- 通過鍵值對進行儲存
- 哈希函數(shù)接受一個關(guān)鍵字,并返回該關(guān)鍵字唯一對應(yīng)的輸出值
這一過程稱為散列(hashing),是輸入與輸出一一對應(yīng)的概念- 哈希函數(shù)為該數(shù)據(jù)返回在內(nèi)存中唯一的存儲地址
要點
- 為查找、插入和刪除而設(shè)計
- 哈希沖突是指哈希函數(shù)對兩個不同的數(shù)據(jù)項產(chǎn)生了相同的輸出值
所有的哈希函數(shù)都存在這個問題- 用一個非常大的哈希表,可以有效緩解這一問題
- 哈希表對于關(guān)聯(lián)數(shù)組和數(shù)據(jù)庫檢索十分重要
時間復(fù)雜度
- O(1)索引:哈希表:O(1)
- O(1)查找:哈希表:O(1)
- O(1)插入:哈希表:O(1)
二叉樹
定義
- 一種樹形的數(shù)據(jù)結(jié)構(gòu),每一結(jié)點最多有兩個子樹
- 子結(jié)點又分為左子結(jié)點和右子結(jié)點
要點
- 為優(yōu)化查找和排序而設(shè)計
- 退化樹是一種不平衡的樹,如果完全只有一邊,其本質(zhì)就是一個鏈表
- 相比于其他數(shù)據(jù)結(jié)構(gòu),二叉樹較為容易實現(xiàn)
- 可用于實現(xiàn)二叉查找樹
- 二叉樹利用可比較的鍵值來確定子結(jié)點的方向
- 左子樹有比雙親結(jié)點更小的鍵值
- 右子樹有比雙親結(jié)點更大的鍵值
- 重復(fù)的結(jié)點可省略
- 由于上述原因,二叉查找樹通常被用作一種數(shù)據(jù)結(jié)構(gòu),而不是二叉樹
時間復(fù)雜度
- 索引:二叉查找樹:O(log n)
- 查找:二叉查找樹:O(log n)
- 插入:二叉查找樹:O(log n)
二、搜索基礎(chǔ)
廣度優(yōu)先搜索
定義
- 一種在樹(或圖)中進行搜索的算法,從根結(jié)點開始,優(yōu)先按照樹的層次進行搜索
- 搜索同一層中的各結(jié)點,通常從左往右進行
- 進行搜索時,同時追蹤當(dāng)前層中結(jié)點的子結(jié)點
- 當(dāng)前一層搜索完畢后,轉(zhuǎn)入遍歷下一層中最左邊的結(jié)點
- 最下層最右端是最末結(jié)點(即該結(jié)點深度最大,且在當(dāng)前層次的最右端)
要點
- 當(dāng)樹的寬度大于深度時,該搜索算法較優(yōu)
- 進行樹的遍歷時,使用隊列存儲樹的信息
- 原因是:使用隊列比深度優(yōu)先搜索更為內(nèi)存密集
- 由于需要存儲指針,隊列需要占用更多內(nèi)存
時間復(fù)雜度
- O(|E| + |V|)查找:廣度優(yōu)先搜索:O(|E| + |V|)
- E 是邊的數(shù)目
- V 是頂點的數(shù)目
深度優(yōu)先搜索
定義
- 一種在樹(或圖)中進行搜索的算法,從根結(jié)點開始,優(yōu)先按照樹的深度進行搜索
- 從左邊開始一直往下遍歷樹的結(jié)點,直到不能繼續(xù)這一操作
- 一旦到達某一分支的最末端,將返回上一結(jié)點并遍歷該分支的右子結(jié)點,如果可以將從左往右遍歷子結(jié)點
- 當(dāng)前這一分支搜索完畢后,轉(zhuǎn)入根節(jié)點的右子結(jié)點,然后不斷遍歷左子節(jié)點,直到到達最底端
- 最右的結(jié)點是最末結(jié)點(即所有祖先中最右的結(jié)點)
要點
- 當(dāng)樹的深度大于寬度時,該搜索算法較優(yōu)
- 利用堆棧將結(jié)點壓棧
- 因為堆棧是“后進先出”的數(shù)據(jù)結(jié)構(gòu),所以無需跟蹤結(jié)點的指針。與廣度優(yōu)先搜索相比,它對內(nèi)存的要求不高。
- 一旦不能向左繼續(xù)遍歷,則對棧進行操作
時間復(fù)雜度
- O(|E| + |V|)查找:深度優(yōu)先搜索:O(|E| + |V|)
- E 是邊的數(shù)目
- V 是結(jié)點的數(shù)目
廣度優(yōu)先搜索 VS. 深度優(yōu)先搜索
- 這一問題最簡單的回答就是,選取何種算法取決于樹的大小和形態(tài)
- 就寬度而言,較淺的樹適用廣度優(yōu)先搜索
- 就深度而言,較窄的樹適用深度優(yōu)先搜索
細微的區(qū)別
- 由于廣度優(yōu)先搜索(BFS)使用隊列來存儲結(jié)點的信息和它的子結(jié)點,所以需要用到的內(nèi)存可能超過當(dāng)前計算機可提供的內(nèi)存(不過其實你不必擔(dān)心這一點)
- 如果要在某一深度很大的樹中使用深度優(yōu)先搜索(DFS),其實在搜索中大可不必走完全部深度。可在 xkcd 上查看更多相關(guān)信息。
- 廣度優(yōu)先搜索趨于一種循環(huán)算法。
- 深度優(yōu)先搜索趨于一種遞歸算法
三、高效排序基礎(chǔ)
歸并排序
定義
- 一種基于比較的排序算法
- 將整個數(shù)據(jù)集劃分成至多有兩個數(shù)的分組
- 依次比較每個數(shù)字,將最小的數(shù)移動到每對數(shù)的左邊
- 一旦所有的數(shù)對都完成排序,則開始比較最左兩個數(shù)對中的最左元素,形成一個含有四個數(shù)的有序集合,其中最小數(shù)在最左邊,最大數(shù)在最右邊
- 重復(fù)上述過程,直到歸并成只有一個數(shù)據(jù)集
要點
- 這是最基礎(chǔ)的排序算法之一
- 必須理解:首先將所有數(shù)據(jù)劃分成盡可能小的集合,再作比較
時間復(fù)雜度
- O(n)最好的情況:歸并排序:O(n)
- 平均情況:歸并排序:O(n log n)
- 最壞的情況:歸并排序:O(n log n)
快速排序
定義
- 一種基于比較的排序算法
- 通過選取平均數(shù)將整個數(shù)據(jù)集劃分成兩部分,并把所有小于平均數(shù)的元素移動到平均數(shù)左邊
- 在左半部分重復(fù)上述操作,直到左邊部分的排序完成后,對右邊部分執(zhí)行相同的操作
- 計算機體系結(jié)構(gòu)支持快速排序過程
要點
- 盡管快速排序與許多其他排序算法有相同的時間復(fù)雜度(有時會更差),但通常比其他排序算法執(zhí)行得更快,例如歸并排序。
- 必須理解:不斷通過平均數(shù)將數(shù)據(jù)集對半劃分,直到所有的數(shù)據(jù)都完成排序
時間復(fù)雜度
- O(n)最好的情況:歸并排序:O(n)
- O(n log n)平均情況:歸并排序:O(n log n)
- 最壞的情況:歸并排序:O(n2)
冒泡排序
定義
- 一種基于比較的排序算法
- 從左往右重復(fù)對數(shù)字進行兩兩比較,把較小的數(shù)移到左邊
- 重復(fù)上述步驟,直到不再把元素左移
要點
- 盡管這一算法很容易實現(xiàn),卻是這三種排序方法中效率最低的
- 必須理解:每次向右移動一位,比較兩個元素,并把較小的數(shù)左移
時間復(fù)雜度
- O(n)最好的情況:歸并排序:O(n)
- O(n2)平均情況:歸并排序: O(n2)
- O(n2)最壞的情況:歸并排序: O(n2)
歸并排序 VS. 快速排序
- 在實踐中,快速排序執(zhí)行速率更快
- 歸并排序首先將集合劃分成最小的分組,在對分組進行排序的同時,遞增地對分組進行合并
- 快速排序不斷地通過平均數(shù)劃分集合,直到集合遞歸地有序
四、算法類型基礎(chǔ)
遞歸算法
定義
- 在定義過程中調(diào)用其本身的算法
- 遞歸事件:用于觸發(fā)遞歸的條件語句
- 基本事件:用于結(jié)束遞歸的條件語句
要點
- 堆棧級過深和棧溢出
- 如果在遞歸算法中見到上述兩種情況中的任一個,那就糟糕了
- 那就意味著因為算法錯誤,或者問題規(guī)模太過龐大導(dǎo)致問題解決前 RAM 已耗盡,從而基本事件從未被觸發(fā)
- 必須理解:不論基本事件是否被觸發(fā),它在遞歸中都不可或缺
- 通常用于深度優(yōu)先搜索
迭代算法
定義
- 一種被重復(fù)調(diào)用有限次數(shù)的算法,每次調(diào)用都是一次迭代
- 通常用于數(shù)據(jù)集中遞增移動
要點
- 通常迭代的形式為循環(huán)、for、while和until語句
- 把迭代看作是在集合中依次遍歷每個元素
- 通常用于數(shù)組的遍歷
遞歸 VS. 迭代
- 由于遞歸和迭代可以相互實現(xiàn),兩者之間的區(qū)別很難清晰地界定。但必須知道:
- 通常遞歸的表意性更強,更易于實現(xiàn)
- 迭代占用的內(nèi)存更少
- (i.e. Haskell)函數(shù)式語言趨向于使用遞歸(如 Haskell 語言)
- 命令式語言趨向于使用迭代(如 Ruby 語言)
- 點擊 Stack Overflow post 了解更多詳情
遍歷數(shù)組的偽代碼(這就是為什么使用迭代的原因)
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
貪婪算法
定義
- 一種算法,在執(zhí)行的同時只選擇滿足某一條件的信息
- 通常包含5個部分,摘自維基百科:
- 候選集,從該集合中可得出解決方案
- 選擇函數(shù),該函數(shù)選取要加入解決方案中的最優(yōu)候選項
- 可行性函數(shù),該函數(shù)用于決策某一候選項是否有助于解決方案
- 目標(biāo)函數(shù),該函數(shù)為解決方案或部分解賦值
- 解決方案函數(shù),該函數(shù)將指明完整的解決方案
要點
- 用于找到預(yù)定問題的最優(yōu)解
- 通常用于只有少部分元素能滿足預(yù)期結(jié)果的數(shù)據(jù)集合
- 通常貪婪算法可幫助一個算法降低時間 復(fù)雜度
偽代碼:用貪婪算法找到數(shù)組中任意兩個數(shù)字間的最大差值
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
這一算法無需比較所有數(shù)字兩兩之間的差值,省略了一次完整迭代。
以下是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
?
計算機科學(xué)中最重要的32個算法
- 查找:判斷某特定元素屬于哪個組。
- 合并:聯(lián)合或合并兩個組為一個組。
現(xiàn)實中算法
Linux內(nèi)核中的基本數(shù)據(jù)結(jié)構(gòu)和算法
B+ 樹,代碼中的注釋將會告訴你一些教科書中不能學(xué)到的內(nèi)容:
這是一個簡單的B+樹實現(xiàn),我寫它的目的是作為練習(xí),并以此了解B+樹的工作原理。結(jié)果該實現(xiàn)發(fā)揮了它的實用價值。
...
一個不經(jīng)常在教科書中提及的技巧:最小值應(yīng)該放在右側(cè),而不是左側(cè)。一個節(jié)點內(nèi)所有被使用的槽位應(yīng)該在左側(cè),沒有使用的節(jié)點應(yīng)該為NUL,大部分的操作只遍歷一次所有的槽位,在第一個NUL處終止。
帶權(quán)重的有序列表用于互斥鎖、驅(qū)動等;
radix樹的一個常見的用法是保存頁面結(jié)構(gòu)體的指針;
包含指針的只允許簡單插入的靜態(tài)大小優(yōu)先級堆,基于CLR(算法導(dǎo)論)第七章
哈希函數(shù),引用Knuth和他的一篇論文:
Knuth建議選擇與機器字長所能表達的最大整數(shù)約成黃金比例的素數(shù)來做乘法散列,Chuck Lever 證實了這個技術(shù)的有效性;
http://www.citi.umich.edu/techreports/reports/citi-tr-00-1.pdf
這些選擇的素數(shù)是位稀疏的,也就是說對他們的操作可以使用位移和加法來替換機器中很慢的乘法操作;
有些代碼,比如這個驅(qū)動,他們是自己實現(xiàn)的哈希函數(shù)
在命名空間樹中執(zhí)行一個修改過的深度優(yōu)先算法,開始(和終止于)start_handle所確定的節(jié)點。當(dāng)與參數(shù)匹配的節(jié)點被發(fā)現(xiàn)以后,回調(diào)函數(shù)將會被調(diào)用。如果回調(diào)函數(shù)返回一個非空的值,搜索將會立即終止,這個值將會回傳給調(diào)用函數(shù);
Knuth-Morris-Pratt 字符串匹配;
Knuth、Morris和 Pratt [1]實現(xiàn)了一個線性時間復(fù)雜度字符串匹配算法。該算法完全規(guī)避了對轉(zhuǎn)換函數(shù)DELTA的顯式計算。其匹配時間為O(n)(其中n是文本長度),只使用一個輔助函數(shù)PI[1...m](其中m是模式的長度),模式的預(yù)處理時間是O(m)。PI這個數(shù)組允許DELTA函數(shù)在需要時能迅速運行。大體上,對任意狀態(tài)q=0,1,...,m和任意SIGMA中的字符"a",PI["q"]保存了獨立于"a"的信息,并用于計算DELTA("q", "a")。由于PI這個數(shù)組只包含m個條目,而DELTA包含O(m|SIGMA|)個條目,我們通過計算PI進而在預(yù)處理時間保存|SIGMA|的系數(shù),而非計算DELTA。
[1] Cormen, Leiserson, Rivest, Stein Introdcution to Algorithms, 2nd Edition, MIT Press
[2] See finite automation theory
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)自右向左做匹配,有一種可能性是一個匹配分布在不同的塊中,這種情況下是不能找到任何匹配的。
如果你想確保這樣的事情不會發(fā)生,使用Knuth-Pratt-Morris(KMP)算法來替代。也就是說,根據(jù)你的設(shè)置選擇合適的字符串查找算法。
如果你使用文本搜索架構(gòu)來過濾、網(wǎng)絡(luò)入侵檢測(NIDS)或者任何安全為目的,那么選擇KMP。如果你關(guān)乎性能,比如你在分類數(shù)據(jù)包,并應(yīng)用服務(wù)質(zhì)量(QoS)策略,并且你不介意可能需要在分布在多個片段中匹配,然后就選擇BM。
Chromium 瀏覽器中的數(shù)據(jù)結(jié)構(gòu)和算法
此樹會被分配策略參數(shù)化,這個策略負責(zé)在C的自由存儲空間和區(qū)域中分配列表,參見zone.h
同時,代碼中還包含了一些第三方的算法和數(shù)據(jù)結(jié)構(gòu),例如:
編程語言類庫
分配和調(diào)度算法
*nix系統(tǒng)中的核心組件
加密算法
編譯器
壓縮和圖片處理
為GIF圖片格式而出現(xiàn)的Lempel-Zivsraf算法在圖片處理程序中經(jīng)常被應(yīng)用,從一個簡單的*nix組件轉(zhuǎn)化為一個復(fù)雜的程序;
運行長度編碼被用于生成PCX文件(用于Paintbrush這個程序中),壓縮BMP文件和TIFF文件;
小波壓縮(Wavelet壓縮)是JPEG 2000的基礎(chǔ),所以所有生成JPEG 2000文件的數(shù)碼相機都是實現(xiàn)了這個算法;
Reed-Solomon糾錯用于Linux內(nèi)核、CD驅(qū)動、條形碼讀取,并且結(jié)合卷積從航行團隊進行圖片傳輸;
沖突驅(qū)動條款學(xué)習(xí)算法(Conflict Driven Clause Learning)
自2000年以來,在工業(yè)標(biāo)準(zhǔn)中的SAT(布爾滿足性問題)求解器的運行時間每年都在成倍減少。這一發(fā)展的一個非常重要的原因是沖突驅(qū)動條款學(xué)習(xí)算法(Conflict Driven Clause Learning)的使用,它結(jié)合了Davis Logemann和Loveland的約束編程和人工智能研究技術(shù)的原始論文中關(guān)于布爾約束傳播的算法。具體來說,工業(yè)建模中SAT被認為是一個簡單的問題(見討論)。對我來說,這是近代最偉大的成功故事之一,因為它結(jié)合了先進的算法、巧妙的設(shè)計思路、實驗反饋,并以一致的共同努力來解決這個問題。Malik和Zhang的CACM論文是一個很好的閱讀材料。許多大學(xué)都在教授這個算法,但通常是在邏輯或形式化方法的課程中。
?
?
希望對您企業(yè)應(yīng)用開發(fā)與企業(yè)信息化有幫助。 其它您可能感興趣的文章:
《視覺直觀感受 7 種常用的排序算法》
《匈牙利 Sapientia 大學(xué)的 6 種排序算法舞蹈視頻》
《視頻:6 分鐘演示 15 種排序算法》
《SORTING:可視化展示排序算法的原理,支持單步查看》
《VisuAlgo:通過動畫學(xué)習(xí)算法和數(shù)據(jù)結(jié)構(gòu)》
軟件開發(fā)的專業(yè)化
IT基礎(chǔ)架構(gòu)規(guī)劃方案一(網(wǎng)絡(luò)系統(tǒng)規(guī)劃)
IT基礎(chǔ)架構(gòu)規(guī)劃方案二(計算機系統(tǒng)與機房規(guī)劃規(guī)劃)?
IT基礎(chǔ)架構(gòu)規(guī)劃方案三(IT基礎(chǔ)軟件和系統(tǒng)規(guī)劃)
企業(yè)應(yīng)用之性能實時度量系統(tǒng)演變
云計算參考架構(gòu)幾例
智能移動導(dǎo)游解決方案簡介
人力資源管理系統(tǒng)的演化
如有想了解更多軟件研發(fā) , 系統(tǒng) IT集成 , 企業(yè)信息化 等資訊,請關(guān)注我的微信訂閱號:
作者:Petter Liu
出處:http://www.cnblogs.com/wintersun/
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。
該文章也同時發(fā)布在我的獨立博客中-Petter Liu Blog。
轉(zhuǎn)載于:https://www.cnblogs.com/wintersun/p/4840585.html
總結(jié)
以上是生活随笔為你收集整理的数据结构与算法 Big O 备忘录与现实的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: QQ聊天文字背影图片拉伸方法
- 下一篇: java 添加一个线程、创建响应的用户界