你必須背下的幾個經典演算法 2nd

2021-06-26 08:49:29 字數 4021 閱讀 1225

(三)紅黑樹

紅黑樹自身具有優秀的平衡性,具有很高效的檢索速度,很適於對有權重的資料進行組織和查詢。紅黑樹首先是一種二叉搜尋樹,因而具有「左下最小、右下最大」的性質。紅黑樹的每個節點(node)至少包括了5個域: 父節點指標、左孩子指標、右孩子指標、關鍵字、顏色,紅黑樹具有如下特性,才使得它具有如此優秀的性質: 

[1]紅黑樹的節點要麼是黑色,要麼是紅色。

[2]根節點是黑色

[3]葉子節點是黑色(根節點和葉子節點一般用乙個唯一的域值為null的null節點表示)

[4]紅色節點的孩子必須是黑色

[5]從任意節點到達葉子節點,所經過的黑色節點數目相等

(其中黑高可以用來特指某個節點到達它的葉子節點的路徑上黑色節點數目,不包括其自身)

乙個紅黑樹的建樹時間是o(n*lg(n)),插入時間是o(lg(n)),刪除時間是o(lg(n)),檢索時間是o(lg(n))。  

二叉搜尋樹的旋轉操作: 

x/   \

a      y

/   \

b      r

旋轉為:

y/   \

x      r

/  \

a     b

不需要額外的指標就能進行旋轉操作,步驟如下

[1] y = x.right 這裡用到了兩個指標,包括乙個引數

[2] x.p.left_or_right = y; y.p = x.p; 

[3] x.right = y.left; y.left.p = x; 

[3] y.left = x; x.p = y; 

紅黑樹的插入:

步驟一: 根據二叉搜尋樹的方法插入節點並且標記為紅色,不考慮節點插入對4個性質的違背

步驟二: 由於可能違背了性質2、(非根)必須違背性質4,進行著色調整。呼叫rb-insert-fixup,分三種情況進行處理:

(1)叔節點為紅色,自身為左孩子或者右孩子均可

(2)叔節點為黑色,自身為左孩子

(3)叔節點為黑色,自身為右孩子

(1)將祖父節點的黑色變為紅色,將黑色分給父節點和叔節點,繼續針對祖父節點遞迴,這樣黑高向下「移」而不變,而且操作僅僅使著色發生變化

(2)對父節點進行右旋操作,並且保持樹的顏色分布,這樣顏色分布不變,僅僅是父節點進行了右旋

(四)基數排序

基數排序的思想是將n個待排元素對應到乙個多位的整數,一共有d位,每一位都可以取值k個值; 對每一位為標準位進行一次穩定的排序,整個元素的順序按照這個標準位進行排列,繼續從低位排序到高位,並對這個元素重新排序; 如果每一次穩定排序的時間是o(n+k),那麼最終時間是o(d*(n+k))。

(五)桶排序

桶排序是針對在一定區間內均勻分布(或近似於均勻分布)的資料進行排序的,所以是一種特殊(非普適)的演算法。我們假設分布的區間是[0, 1),對這個長度為1的區間分成n個小區間(我們稱之為桶),每個區間長度為1/n,每乙個小區間對應乙個鍊錶,當新資料輸入時,我們將輸入資料逐個地和桶的標準分界值比較,當輸入資料落入某個區間時,將它插入到對應的鍊錶中去,在插入的時候又可以進行比較從而使得鍊錶內資料有序。當所有輸入完成後,將所有鍊錶(除了頭節點)鏈結起來,形成乙個總的鍊錶。

(六)動態規劃

演算法基本思想是分治:將問題分解為若干個子問題,但是要進行中間結果(即子問題的解)的記錄,在繼續計算時,會多次使用前面的中間結果,將這些子問題的解有序地組合起來,一般可以組成乙個二維陣列,備存便用,這成為了動態規劃的最大特徵。可見動態規劃是一種犧牲空間換取時間為代價的,中間結果放在儲存表中。利用這種思想對遞迴方法進行改進得到了記憶型遞迴,即每次遞迴到子問題時先查詢是否有中間解,沒有繼續遞迴,否則直接使用已得結果,如矩陣鏈乘法。

動態規劃的使用還有乙個重要的原則:即子問題的原問題的最優解的必要條件,即如果最終的解是最優的,那麼解的每乙個細分(按照子問題劃分)或每乙個步驟都是最優的。比如最短路徑問題,它的子步驟是到達終點的路徑分段,即包含終點的子路徑的選擇(從後向前),要確保每乙個字分段都是最優的。即如果

(七)0-1揹包問題

演算法的思想簡單,是基本的遞迴思路,只不過在每一層遞迴時,考慮下乙個物品的取捨,以及下一物品是否「超重」,總是遵循「累計」價值最大以及「超重不取」的原則,而不是「能裝則取」。

不過在構造儲存表時需要更多的技巧,這是乙個矩陣(二維陣列),i下標代表剩餘的物品數,j下標代表剩餘的容量。由於二維陣列下標是連續變化的,所以對每乙個單位的剩餘重量都要分配儲存空間和初始化值,這裡考慮的臨界條件比較巧妙,對陣列元素賦的初值經過了精心設計:a.對於取最後乙個物品的,即剩餘n個物品的初值,假設w[n] <= c,即能裝的下最後乙個物品(最後乙個指的是第n個而不是時間上的概念),則對映到這個冗餘的儲存陣列時,從m[n][w[n]]到m[n][c]都要賦一樣的初值,因為這時只能取乙個物品n,並且取完之後使得m[n][.](.代表上述範圍內的值)是,考慮了第n個物品的取捨之後的,所能取得物品的最大價值,即m[n][w[n]...c] = w[n],;這裡進一步考慮對於第n個物品,元素下標j

為0到w[n]-1的情況,雖然在目前看來不可能,因為我們的物品n重量w[n]c,裝不下最後乙個物品,對於則只能對這些值賦0,即考慮第n個物品的取捨之後,得到的總的最大價值仍然是0,也就是m[n][0...c] = 0。歸納以上兩種情況,令maxj = min(w[n] - 1, c),有m[n][0...maxj] = 0; m[n][w[n]...c] =  w[n]; (注意:這裡w[n]...c在遇到w[n] > c的情況時,認為賦值不會被執行)

重複以上思路,對於0...c(...表「到」)即全部的重量範圍,無論還剩餘多少個n-1以內的物品,都無法估算出,考慮了這些物品後,能夠獲得的最大價值;因為在考慮這些物品時,至少還要考慮對是否選擇第n個物品,由此產生的最大價值的比較問題(第n個物品有可能選有可能在裝不下時不選),從而無法賦初值。其中又可以分為兩種情況:a.w[i] <= c,可以放得下第i個物品,這時與第n個物品的取捨不同,要考慮取還是不取第i件物品,因為這直接影響到在子問題的解當中做的選擇,所以有 m[i][j] = max(m[i+1][j-w[i]] + v[i], m[i+1][j]),j = w[i]...c; m[i][j] = m[i+1][j],j = 0...w[i]-1(這裡考慮到為了提供剩餘容量在選擇下乙個物品後可能會受到限制,而儲存的可供選擇的數值,即物品i沒有被選擇時容量不變)。b.w[i] > c,放不下物品i,m[i][j] = m[i+1][j],j = 0...c。歸納來說,就是maxj = min(w[i] - 1, c),有m[i][j] = m[i+1][j],j = 0...maxj

;m[i][j] = max(m[i+1][j-w[i]] + v[i], m[i+1][j]),j = w[i]...c。

在這裡,又有乙個細節性的關鍵問題,在這個演算法中,取第i件物品影響的不是還沒有的取得物品,而是自身的問題最大價值,這裡要考慮的是選取物品i使得剩餘空間減少的情況下子問題的最大值 和 不選取物品i的剩餘空間下子問題的最大值,而不是第i+1件物品已經確定,剩餘容量大小和i的增減之間也沒有正相關的關係,只是第i+1件物品的子問題提供了在不同剩餘空間下最大價值的子問題解的選擇而已;具體地說,這裡用到的反向思維方式,即我們的問題的最優解取決於子問題的最優解,而子問題的最優解是已經解決的問題的解和當前考慮的新元素對應的情況處理組合,而不是僅僅是在子問題解中選擇最大價值的解,這裡我們要在i+1物品的考慮點上,對兩個不同的剩餘容量儲存值對應的價值之間進行選擇,即選擇採用m[i+1][j]還是m[i+1][j-w[i]]。這有悖於正常思維,因為我們可能認為第i+1個物品已經選過,而對它的選擇取還是不取,考慮時剩餘的揹包容量空間應該固定的,而這裡卻受到第i個物品的取捨的影響。這裡,正是這個演算法的精髓所在,即在考慮某個物品時,要考慮所有的容量空間,在這些容量空間下,取捨該物品所能得到的總的價值都要計算。 這樣,在選取之後的第i件物品時,第i件物品的取捨直接影響到對於第i+1個子問題解的選擇範圍,這裡的選擇範圍是取或不取第i件物品造成的剩餘容量的限制,具體地說,就是選取第i件物品時在剩餘容量下取最大價值的子問題的解,和在不取第i件物品時在剩餘容量下取最大價值的子問題的解,在這基礎上再考慮第i件物品的選取帶來的價值,由此作出選擇。

用數學表示式表示如下:

你必須知道的幾個救命常識

個案1 有一婦女手提包被偷,裡面有手機 hidden 錢包等。20分鐘後,她打通了老公的 告訴自己被偷的事。老公驚呼 啊,我剛才收到你的簡訊,問咱家hidden的密碼,我立馬就回了!他們趕到銀行時,被告知裡面所有的錢都已被提走。小偷通過用偷來的手機傳送簡訊給 親愛的老公 而獲取了密碼,然後在短短20...

你必須學會的幾個常用網路測試命令

如果你是乙個網路維護人員,那麼肯定要經常處理網路故障,了解和掌握下面幾個命令將會有助於您更快地檢測到網路故障所在,從而節省時間,提高效率。ping ping是測試網路聯接狀況以及資訊包傳送和接收狀況非常有用的工具,是網路測試最 常用的命令。ping向目標主機 位址 傳送乙個回送請求資料報,要求目標主...

你必須要知道的幾個CSS技巧

有些經典的css技巧,我們還是需要記住的,這樣可以節省我們大量的時間,下面零度就為大家推薦幾個比較好的css技巧 許多網頁上都有導航選單,當進入某頁時,選單上相應這一項就應該變灰,而其他頁亮起來。一般要實現這個效果,需要寫程式或專門為每一頁做設計,現在靠css就可以實現這個效果。首先,在導航 中使用...