讀書筆記_演算法第四版(二)
演算法第四版(謝路雲譯)
第4章 圖
4.1 無向圖
l 圖是由一組頂點和一組能夠將兩個頂點相連的邊組成的。
l 自環:即一條連線一個頂點和其他自身的邊。平行邊:連線同一對頂點的兩條邊。多重圖:含有平行邊的圖。簡單圖:沒有平行邊或自環的圖。
l 路徑,簡單路徑,簡單環,路徑或環的長度,連通,連通圖。樹是無環連通圖。森林,連通圖的生成樹,生成樹森林。
l 度數:某個頂點的度數就是依附於它的邊的總數。圖的密度,稀疏圖,稠密圖,二分圖。
l 圖的表示應該滿足:它必須為可能在應用中碰到的各種型別的圖預留出足夠的空間;例項方法的實現一定要快。待選:鄰接矩陣(空間不能滿足且不能表示平行邊),邊的陣列(簡單但是不快),鄰接表陣列(滿足條件)。
l 深度優先搜尋:深度優先搜尋標記與起點連通的所有頂點所需的時間和頂點的度數之和成正比,和路徑的長度成正比。(小巧而又強大的演算法)
l Tremaux搜尋(走迷宮)。
l 廣度優先遍歷:解決單點最短路徑問題。(所需的時間在最壞情況下和V+E成正比)
l 對於從s可達的任意頂點v,廣度優先搜尋都能找到一條從s到v的最短路徑(沒有其他從s到v的路徑所含的邊比這條路徑更少)。
l 深度優先搜尋的與預處理使用的時間和空間與V+E成正比且可以在常數時間內處理關於圖的連通性查詢。
l 解決圖連通性問題時union-find演算法其實更快,因為不需要對圖進行預處理,因此在完成只需要判斷連通性或是需要完成有大量連通性查詢和插入操作混合等類似的任務時,更傾向使用union-find演算法。
l 檢測環:給定的圖是否含有環。
l 雙色問題:給定圖是否是二分圖。
l 以下為“答疑”和“練習”中的知識點:
l 不把所有的演算法都實現在Graph.java中是避免寬介面。
l 頂點v的離心率是它和離它最遠的頂點的最短距離。圖的直徑即所有頂點的最大離心率,半徑為所有頂點的最小離心率,中心為離心率和半徑相等的頂點。圖的周長是圖中最短環的長度,如果是無環圖,則它的周長為無窮大。
l 尤拉環:圖中經過每條邊一次且僅一次的環。哈密爾頓環是指不重複地走過所有的點,並且最後還能回到起點的迴路。
4.2 有向圖
l 有向圖:由一組頂點和一組有方向的邊組成的,每條有方向的邊都連線著有序的一對頂點(頂點分別稱為頭和尾)。
l 單點可達性:是否存在一條從s到給定頂點v的有向路徑。多點可達性:是否存在一條從集合中的任意頂點到達給定頂點v的有向路徑。在有向圖中,深度優先搜尋標記由一個集合的頂點可達的所有頂點所需的時間與被標記的所有頂點的出度之和成正比。
l 單點有向路徑,單點最短有向路徑。優先順序限制下的排程問題。拓撲排序:給定一幅有向圖,將所有的頂點排序,使得所有的有向邊均從排在前面的元素指向排在後面的元素(或者說明無法做到這一點)。拓撲排序典型應有:任務排程,課程安排,繼承,電子表格,符號連結。
l 如果一個有優先順序限制的問題中存在有向環,那麼這個問題一定是無解的。有向無環圖(DAG):就是一幅不含有向環的有向圖。
l 當且僅當一幅有向圖是無環圖時它才能進行拓撲排序。一幅有向無環圖的拓撲排序即為所有頂點的逆後序排列。使用深度優先搜尋對有向無環圖進行拓撲排序所需的時間和V+E成正比。
l 解決任務排程類應用通常需要以下三步:指明任務和優先順序條件;不斷檢測並去除有向圖中的所有環以確保存在可行方案;使用拓撲排序解決排程問題。
l 強連通:兩個頂點互相可達。強連通圖:一幅有向圖中任意兩個頂點都是強連通的。強連通性具有:自反性,對稱性,傳遞性。
l Kosaraju演算法:高效計算強連通分量。使用深度優先查詢給定有向圖G的方向圖GR,根據由此得到的所有頂點的逆後序再次深度優先搜尋處理有向圖G(Kosaraju演算法),其建構函式中的每一次遞迴呼叫所標記的頂點都在同一個強連通分量之中。Kosaraju演算法的預處理所需的時間和空間與V+E成正比且支援常數時間的有向圖強連通性的查詢。
4.3 最小生成樹
l 加權圖:是一種每條邊關聯一個權值或是成本的圖模型。
l 圖的生成樹:是它的一棵含有其所有頂點的無環連通子圖。
l 一幅加權圖的最小生成樹(MST)是它的一棵權值(樹中所有邊的權值之和)最小的生成樹。
l 一些約定:只考慮連通圖(非連通圖不存在最小生成樹,只有最小生成森林);邊的權重不一定表示距離;邊的權重也可能是0或者負數(邊權重都為正數的話最小生成樹定義為連線所有頂點且總權重最小的子圖就足夠了);所有邊的權重都各不相同(若權重可以相同那麼最小生成樹就不一定是唯一的了,但這個假設並不會限制演算法的適用範圍)。
l 圖的一種切分是將圖的所有頂點分為兩個非空且不重疊的兩個集合。橫切邊是一條連線兩個屬於不同集合的頂點和邊。
l 切分定理:在一幅加權圖中,給定任意的切分,它的橫切邊中的權重最小者必然屬於圖的最小生成樹。
l 最小生成樹的貪心演算法:下面這種方法會將含有V個頂點的任意加權連通圖中屬於最小生成樹的邊標記為黑色:初始狀態下所有邊均為灰色,找到一種切分它產生的橫切邊均不為黑色,將它權重最小的橫切邊標記為黑色,反覆,知道標記了V-1條黑色邊為止。
l Prim演算法:計算最小生成樹的方法,它的每一步都會為一棵生長中的樹新增一條邊,一開始這棵樹只有一個頂點,然後會向它新增V-1條邊,每次總是將下一條連線樹中的頂點與不在樹中的頂點且權重最小的邊(黑色表示)加入樹中(即由樹中的頂點所定義的切分中的一條橫切邊)。能夠計算任意加權連通圖的最小生成樹。
l Prim演算法的延時實現計算一幅含有V個頂點和E條邊的連通加權無向圖的最小生成樹所需的空間與E成正比,所需的時間與ElogE成正比(最壞情況)。
l Prim演算法的即時實現計算一幅含有V個頂點和E條邊的連通加權無向圖的最小生成樹所需空間和V成正比,所需的時間和ElogV成正比(最壞情況)。
l Kruskal演算法:按照邊的權重順序(從小到大)處理它們,將邊加入最小生成樹中(圖中的黑色邊),加入的邊不會與已經加入的邊構成環,直到樹中含有V-1條邊為止。這些黑色的邊逐漸由一片森林合併為一棵樹,也就是圖的最小生成樹。Kruskal演算法能能夠計算任意加權連通圖的最小生成樹。
l Kruskal演算法的計算一幅含有V個頂點和E條邊的連通加權無向圖的最小生成樹所需的空間和E成正比,所需的時間和ElogE成正比(最壞情況)。
l Prim演算法和Kruskal演算法不能處理有向圖處理問題。有向圖更難,稱為最小樹形圖問題。
4.4 最短路徑
l 在一幅加權有向圖中,從頂點s到頂點t的最短路徑是所有從s到t的路徑中的權重最小者。
l 最短路徑的性質:路徑是有向的;權重不一定等價於距離;並不是所有頂點就是可達的;負權重會使問題更復雜;最短路徑一般都是簡單的;最短路徑不一定是唯一的;可能存在平行邊和自環。
l 最短路徑樹:給定一幅加權有向圖和一個頂點s,以s為起點的一棵最短路徑樹是圖的一幅子圖,它包含s和從s可達的所有頂點。這棵有向樹的根結點為s,樹的每條路徑都是有向圖中的一條最短路徑。
l 放鬆操作(relax):放鬆邊v->w意味著檢查從s到w的最短路徑是否是先從s到v,然後再由v到w。如果是,則根據這個情況更新資料結構的內容。由v到達w的最短路徑是distTo[v]與e.weight()之和,如果這個值不小於distTo[w],稱這條邊失效了並將它忽略,如果這個值更小就更新資料。(鬆弛術語來源於橡皮筋比喻:放鬆一條邊就像將橡皮筋轉移到一條更短的路徑上,從而緩解了橡皮筋的壓力)
l 最短路徑的最優性條件:令G為一幅加權有向圖,頂點s是G中的起點,distTo[]是一個由頂點索引的陣列,儲存的是G中路徑的長度,對於從s可達的所有頂點v,distTo[v]的值是從s到v的某條路徑的長度,對於從s不可達的所有頂點v,該值為無窮大。當且僅當對於從v到w的任意一條邊e,這些值都是滿足distTo[w]<=distTo[v]+e.weight()時(換句話說,不存在有效邊時),它們是最短路徑的長度。
l 通用最短路徑演算法:將distTo[s]初始化為0,其他distTo[]元素初始化為無窮大,繼續如下操作:放鬆G中的任意邊,直到不存在有效邊為止。對於任意從s可達的頂點w,在進行這些操作之後,distTo[w]的值即為從s到w的最短路徑的長度(且edgeTo[w]的值即為該路徑上的最後一條邊)。
l Dijkstra演算法:首先將distTo[s]初始化為0,distTo[]中的其他元素初始化為正無窮,然後將distTo[]最小的非樹頂點放鬆並加入樹中,如此這般,直到所有的頂點都在樹中或者所有的非樹頂點的distTo[]值均為無窮大。Dijkstra演算法能夠解決邊權重非負的加權有向圖的單起點最短路徑問題。
l 在一幅含有V個頂點和E條邊的加權有向圖中,使用Dijkstra演算法計算根結點為給定起點的最短路徑樹所需的空間與V成正比,時間與ElogV成正比(最壞情況下)。
l 無環加權有向圖中的最短路徑演算法:能夠線上性時間內解決單點最短路徑問題;能夠處理負權重的邊;能夠解決相關的問題,例如找出最長的路徑。
l 按照拓撲排序放鬆頂點,就能在和E+V成正比的時間內解決無環加權有向圖的單點最短路徑問題。
l 解決無環加權有向圖中的最長路徑問題所需的時間與E+V成正比。
l 解決並行任務排程問題的關鍵路徑方法的步驟如下:建立一幅無環加權有向圖,其中包含一個起點s和一個重點t且每個任務都對應著兩個頂點(一個起始頂點和一個結束頂點)。對於每個任務都有一條從它的其實頂點指向結束頂點的邊,邊的權重為任務所需的時間。對於每條優先順序限制v->w新增一條從v的結束頂點指向w的起始頂點的權重為0的邊。我們還需要為每個任務新增一條從起點指向該任務的其實頂點的權重為0的邊以及一條從該任務的結束頂點到終點的權重為0的邊。這樣每個任務預計的開始時間即為從起點到它的起始頂點的最長距離。
l 解決優先順序限制下的並行任務排程問題的關鍵路徑演算法所需的時間為線性級別。
l 相對最後期限限制下的並行任務排程問題是一個加權有向圖中的最短路徑問題(可能存在環和負權重邊)。
l 負權重環:加權有向圖中的負權重環是一個總權重(環上的所有邊的權重之和)為負的有向環。(繞著這個環一直轉圈子就能將總權重降到任意小的權重值)
l 當且僅當加權有向圖中至少存在一條從s到v的有向路徑且所有從s到v的有向路徑上的任意頂點都不存在與任何負權重環中時,s到v的最短路徑才是存在的。
l Bellman-Ford演算法:在任意含有V個頂點的加權有向圖中給定起點s,從s無法到達任何負權重環,以下演算法能夠解決其中的單點最短路徑問題:將distTo[s]初始化為0,其他distTo[]元素初始化為無窮大,以任意順序放鬆有向圖的所有邊,重複V輪。Bellman-Ford演算法所需的時間和EV成正比,空間和V成正比;
l 套匯問題等價於加權有向圖中的負權重環的檢測問題。
第5章 字串
l 字元,不可變性,索引,長度,子字串,字串的連線,字元陣列,字元索引陣列,數字。
5.1 字串排序
l 低位優先(Least-Significant-Digit-First):從右到左檢查鍵中的字元,最適合用於鍵長度都相同的字串排序應用。
l 高位優先(Most-Significant-Digit-First):從左到右檢查鍵中的字元。
l 鍵索引計數法:適用於小整數鍵的簡單排序方法。鍵索引計數法排序N個鍵為0到R-1之間的整數的元素需要訪問陣列11N+4R+1次。
l 低位優先的字串排序演算法能夠穩定地將定長字串排序。
l 對於基於R個字元的字母表的N個以長為W的字串為鍵的元素,低位優先的字串排序需要訪問~7WN+3WR次陣列,使用的額外空間與N+R成正比。
l 高位優先的字串排序對字串末尾處理需要特別注意,小型子陣列切換到插入排序是必要的,含有大量等值鍵的子陣列排序會比較慢。
l 要將基於大小為R的字母表的N個字串排序,高位優先的字串排序演算法平均需要檢查NlogRN個字元;訪問陣列的次數在8N+3R到~7wN+3wR之間,其中w是字串的平均長度;最壞情況下高位優先的字串排序演算法所需的空間與R乘以最長的字串的長度之積成正比(再加上N)。
l 三向字串快速排序:根據高位優先的字串排序演算法改進快速排序,根據鍵的首字母進行三向切分,僅在中間子陣列中的下一個字元(因為鍵的首字母都與切分字元相等)繼續遞迴排序。要將含有N個隨機字串的陣列排序,三向字串快速排序平均需要比較字元~2NlnN次。
5.2 單詞查詢樹
l 值為空的結點在符號表中沒有對應的鍵,它們的存在是為了簡化單詞查詢樹中的查詢操作。
l R向單詞查詢樹:基於含有R個字元的字母表的單詞查詢樹。結點儲存一個value值為從根結點到該結點合起來的字串,儲存一個大小為R的子連結陣列。
l 單詞查詢樹的連結串列結構(形狀)和鍵的插入或刪除順序無關:對於任意給定的一組鍵,其單詞查詢樹都是唯一的。
l 在單詞查詢樹中查詢一個鍵或者插入一個鍵時,訪問陣列的次數最多為鍵的長度加1。
l 字母表的大小為R,在一棵由N個隨機鍵構造的單詞查詢樹中,未命中查詢平均所需檢查的結點數量為~logRN。
l 一棵單詞查詢樹中的連結總數在RN到RNw之間,其中w為鍵的平均長度。(當所有鍵均較短時連結總數接近於RN;當所有鍵均較長時連結總數接近於RNw;縮小R能節省大量的空間)
l 單向分支:解決長尾巴問題。
l 三向單詞查詢樹:每個結點含有一個字元、三條連結和一個值,三條連結對應當前字母小於等於大於結點字母的所有鍵。
l 由N個平均長度為w的字串構造的三向單詞查詢樹中的連結總數在3N到3Nw之間。
l 在一棵由N個隨機字串構造的三向單詞查詢樹中,查詢未命中平均需要比較字元~lnN次。除~lnN次外,一個插入或命中的查詢會比較一次被查詢的鍵中的每個字元。
l 三向單詞查詢樹最大好處是它能夠很好地適應實際應用中可能出現的被查詢鍵的不規則性。(實際應用中的鍵來自大型字母表而各字元使用非常不均衡,且實際應用程式中的鍵常常有著類似的結構)
l 由N個隨機字串構造的根結點進行了Rt向分支且不含有外部單向分支的三向單詞查詢樹中,一個插入或查詢操作平均需要進行約lnN-tlnR次字元比較。
5.3 子字串查詢
l 暴力子字串查詢演算法:用一個指標i跟蹤文字,一個指標j跟蹤模式。最壞情況下,其在長度為N的文字中查詢長度為M的模式需要~NM次字元比較。
l Knuth-Morris-Pratt子字串查詢演算法(KMP演算法):主要思想是提前判斷如何重新開始查詢,這種判斷只取決於模式本身。
l 對於長度為M的模式字串和長度為N的文字,KMP字串查詢演算法訪問的字元不會超過M+N個。
5.4 正則表示式
l
5.5 資料壓縮
l 資料壓縮的基礎模型(兩個能夠讀寫位元流的黑盒子):1、壓縮盒,能夠將一個位元流B轉化為壓縮後的版本C(B)。2、展開盒,能夠將C(B)轉化回B。(無失真壓縮模型)
l 不存在能壓縮任意位元流的演算法。
l 遊程編碼:一長串重複的位元,用前4位表示長度,然後是0或者1。典型應用為點陣圖的無失真壓縮。隨著解析度的提高遊程編碼的效果會大大提高。
l 霍夫曼壓縮(Huffman)(變長字首碼):所有字元編碼都不會稱為其他字元編碼的字首,便是字首碼(不需要分隔符)。霍夫曼壓縮不僅對於自然語言而且對各種來誒性的檔案都有效果。
l 對於任意字首碼,編碼後的位元字串的長度等於相應單詞查詢樹的加權外部路徑。加權外部路徑長度是所有葉子的權重(頻率)和深度之積的和。
l 給定一個含有r個字元的集合和它們的頻率,霍夫曼演算法所構造的字首碼是最優的。
l LZW壓縮演算法:
第6章 背景
6.2 B-樹
l B-樹的成本模型:我們使用頁的訪問次數(無論讀寫)作為外部查詢演算法的成本模型。這裡用來泛指基於固定頁大小的多向平衡查詢樹的資料結構。
l 一棵M階B-樹(M為正偶數)或者僅是一個外部k-結點(含有k個鍵和相關資訊的樹),或者由若干內部k-結點(每個結點都含有k個鍵和k條連結,連結指向的子樹表示了鍵之間的間隔區域)組成,它的結構性質如下:從根結點到每個外部結點的路徑長度均相同(完美平衡);對於根結點,k在2到M-1之間,對於其他結點k在M/2到M-1之間。
l 含有N個元素的M階B-樹中的一次查詢或插入操作需要logMN~logM/2N次探查,在實際情況下這基本是一個常數。
6.4 網路流演算法
l 一個流量網路是一張邊的權重(這裡稱為容量)為正的加權有向圖。一個st-流量網路有兩個已知的頂點,即起點s和終點t。
l st-流量網路中的st流量配置是由一組和每條邊相關聯的值組成的集合,這個值被稱為邊的流量。如果所有邊的流量均小於邊的容量且滿足每個頂點的區域性平衡(即流入量等於流出量,淨流量為0,s和t除外),那麼久稱這種流量配置方案是可行的。
l 最大st-流量:給定一個st-流量網路,找到一種st-流量配置,使得從s到t的流量最大化。
l Ford-Fulkerson最大流量演算法(增廣路徑演算法):網路中的初始流量為0,沿著任意從起點到終點(且不含有飽和的正向邊或是空逆向邊)的增廣路徑增大流量,直到網路中不存在這樣的路徑為止。
l 未完。