堆·左式堆


一、定義

​ 左式堆是為了有效的支持合並操作(merge),將2個堆進行合並,不只是合並2個數組,還要維護其中的堆結構。左式堆像二叉堆那樣具有結構性和有序性。也有堆序性質,也是二叉樹,但它不是平衡的,而是趨向於非常不平衡。

1.1 一些特點和定義

​ 我們為左式堆做如下定義:

  • 零路徑長(npl):任意節點X到一個不具有2個兒子的節點最短路徑長

  • 具有0個兒子或1個兒子的節點的npl為0;

  • npl(null)= -1;

    根據以上定義可知,任意節點的npl比它各個兒子節點的npl的最小值大1,這個節點也是用少於2個兒子的節點,因為null的npl定義為-1。

二、性質

對於堆中的每一個節點X,左兒子的零路徑長至少與右兒子的零路徑長相等。

​ 圖解:

如上圖1,在右圖中,紅色框中的子節點B和子節點C,作為左兒子的B節點的npl是0,而作為右兒子的C節點npl是1,並不滿足左式堆的性質。

​ 左式堆的性質趨向於加深左路徑,所以右路徑應該短,事實上,沿着左式堆的右側的右路徑確實是該堆中最短的路徑。否則就會破壞左式堆的性質。

左式堆的性質,就是不平衡的,顯然它就是為了讓樹往左邊加深。這樣做更利於合並,正因如此,我們定義它為左式堆。

定理一:在右路徑上有r個節點的左式樹必定有\(2^r -1\) 個節點。

右路徑:節點的右兒子的右兒子的右兒子的右兒子的右兒子組成的路徑….就是一只往右兒子下去。

​ 數學歸納法:

r = 1時,必然存在一個節點,至少存在根節點,也許有左節點。

r = 2時,右一個右兒子,那么根據左式堆性質,必然存在一個左兒子。節點\(N \ge 3\)(根節點+左兒子+右兒子)。

r = 3時,r = 4時…..只要滿足二叉堆的性質。那么子樹必定大於右子樹的節點數目。很容易就能得到規律。

三、操作

​ 對左式堆最基礎也是最重要的操作就是合並

3.1 合並(merge)

說明:

  • 插入是簡單的合並,看作一個左式堆與另一個節點數等於1的左式堆的合並。
  • 合並空堆不需要操作,直接返回非空的堆作為結果。
  • 最后得到的堆也是左式堆。

過程圖解:



過程描述:

  1. 我們遞歸的將H1的右子堆(節點8)和H2合並,得到圖3。(根據遞歸法則,我們把一棵樹是空的時候作為基准情形,能處理基准情形自然能遞歸完成)

  2. 我們將圖3的結果作為H1的右子堆,得到圖4。(滿足堆序性質,但是不滿足左式堆性質

  3. 我們將圖4的結果的堆的左右子樹交換,得到圖5,(是個左式堆)

    遞歸法則:

    1.基准情形。必須總要有某些基准情形,它無需遞歸就能解出。

    2.不斷推進。對於那些需要遞歸求解的情形,每一次遞歸調用都必須要使狀況朝向一種基准情形推進。

    3.設計法則。假設所有的遞歸調用都能運行。

    4.合成效益法則(compound interest rule)。在求解一個問題的同一實例時,切勿在不同的遞歸調用中做重復性的工作。

結果分析:

​ 執行合並的時間與諸右路徑的長的和成正比,因為在遞歸調用期間對每一個被訪問的節點花費的是常數工作量。因此,我們得到合並兩個左式堆的時間界為\(O(logN)\)

關於時間界\(O(logN)\):

二叉樹的訪問時間為\(O(logN)\),這是為什么呢,很明顯,\(logN\)為二叉樹的高,二叉樹本來就是一層層尋找,所以得到這個時間界。而堆作為二叉樹的一種,遞歸的操作是循環訪問樹節點,根據遞歸法則4,不存在重復的情況下, 訪問節點時間就是\(O(logN)\)

代碼地址

https://github.com/dhcao/dataStructuresAndAlgorithm/blob/master/src/chapterSix/LeftistHeap.java


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM