diff程式的演算法

2021-05-21 19:34:55 字數 1391 閱讀 3857

diff程式很重要,linux中的源**補丁都是diff作出來的,diff在比較兩個文字檔案的不同方面很高效,它是基於行的,diff會將兩個檔案都按照行分成若干部分,然後計算這些行每一行的校驗碼,之後的問題就是比較這兩個檔案的所有行的校驗碼序列的不同了,這就把問題歸結為了序列比對,diff用的是動態規劃演算法,動態規劃和貪心演算法相似,但是其思想卻是相反的,貪心演算法保證每一步都是最小代價的,但是不能保證最終代價最小,而動態規劃每一步什麼也不知道,它從起點開始,只管區域性地按照要求將無所謂的結果鋪滿全域性,然後回溯,在這些繁複的資料之間找到一條從開始到最後的一條路徑,為何這條路徑就是結果呢?因為每一步都符合要求,所以無論如何最終隨便一條按照要求的回溯路線都符合要求,可是可以看出,這條回溯路線的結果是乙個正確結果但是卻不是唯一的結果,正所謂條條大道通羅馬。和貪心演算法一樣,隨便的一條回溯路線不一定是最佳的,尋找最佳結果還要靠別的機制,貪心演算法比動態規劃好的就是靠近最佳結果的機率更大些,而動態規劃只是乙個結果,它旨在找到一種方案,然而動態規劃有自己的優勢,就是如果你的模型建的好,那麼它可以在每一步很輕鬆的情況下達到同樣的效果,關鍵就是建模。

diff的演算法就是乙個動態規劃的例子,比如乙個校驗碼序列p有m個元素,另乙個q有n個元素,它構建乙個(m+1)*(n+1)的矩陣,然後引出一條蛇,蛇頭勇往直前,呵呵,其實就是往矩陣裡面的元素裡填數字,從(0,0)一直到(m+1,n+1)的大方向填數字,保證所填的數字單調增長,也就是填入的數字不能比它的參照值小,將要填入的是vi,j,那麼它的參照值就是vi-1,j-1,vi-1,j和vi,j-1,具體怎麼做到呢?v值的增加只有一種可能性就是在pi和qj相等的情況下,其它情況下都是不增加的,所以vi,j的值就是三者中最大的,vi,j的參考值不是有三個嗎?那麼這種增加的情況和哪個參考值有關聯呢?事實上是和對角的那個,也就是和vi-1,j-1,仔細想一下,只有i和j同步增長才是p和q的同步推進引起的比較,i和j的單獨推進只是p序列或者q序列的單獨向前推進,也就是說在序列比對的時候就是乙個gap,這種方式填表很簡單,只要有左上,上,左三個值就可以求出當前的這個值,每一步都是那麼的區域性,最終填完後,找到最大的這個值的位置,很顯然是最右下角的這個,然後回溯,怎麼回溯呢?乙個乙個的找到當前值的前驅值所在的位置就可以了,最後將回溯的道路進行標註,得到了p和q的兩條路徑,每寫乙個字元,如果路徑和字串行的方向垂直,那麼就寫乙個空格,最終的結果就是diff的結果,很巧妙吧。不過以上的方式回溯寫出來的路徑不止一條,每一條路徑都是乙個結果。

我們可以看出,每一步都是機械的既定規律的模仿,沒有什麼技巧可言,和貪心演算法幾乎一樣,都是區域性的,但是diff演算法的每一步並沒有和全域性的聯絡起來,知道完成了整個填充之後才在回溯的時候和全域性的結果相聯絡,而貪心演算法的每乙個都記著自己在幹什麼,不需要回溯,這個意義上可以看出diff演算法的填充過程更像是乙個規整過程而不是乙個十足的計算過程,貪心演算法顯得一直很努力,而diff這裡所用的演算法會耍一些技巧,你不是看不出我在做社麼嗎,別急,等會我回溯,一條路徑被勾勒出來了。

diff演算法 diff演算法介紹

diff演算法的作用 計算出virtual dom中真正變化的部分,並只針對該部分進行原生dom操作,而非重新渲染整個頁面。傳統diff演算法 通過迴圈遞迴對節點進行依次對比,演算法複雜度達到 o n 3 n是樹的節點數,這個有多可怕呢?如果要展示1000個節點,得執行上億次比較。即便是cpu快能執...

vue的diff演算法

1.當資料發生變化時,vue是怎麼更新節點的?渲染真實dom的開銷很大,比如我們修改了某個資料,如果直接渲染到真實dom會引起整個dom樹的重繪和重排,有沒有可能我們只更新我們修改的那一小塊dom而不更新整個dom呢?diff演算法可以幫助我們。我們根據真實dom生成乙個虛擬dom,當虛擬dom某個...

React的Diff演算法

要掌握react的diff演算法我們必須先了解一下其渲染的機制 在每一次的狀態或者屬性更新的時候,react元件的render方法會進行渲染,返回乙個虛擬dom物件,這個就是react的渲染機制。但是這裡就有個問題,每次生成新的dom結構,也還是要轉化為真實的dom,還是會帶來大量的真實dom的操作...