最大堆/最小堆【大根堆/小根堆】


堆的定義是:n個元素的序列{k1,k2,…,kn},當且僅當滿足如下關系時被成為堆

    (1)Ki <= k2i 且 ki <= k2i-1       

  或 (2) Ki >= k2i 且 ki >= k2i-1 

          (i = 1,2,…[n/2])

當滿足(1)時,為最小堆,當滿足(2)時,為最大堆。

 

  若將此序列對應的一維數組堪稱是一個完全二叉樹,則2i和2i+1個節點分別是節點i的左右子節點。

如下為一個最大堆:

下面以最小堆為例說明堆的輸出

  圖1為一個最小堆,當最小節點根節點13輸出后,將最后一個節點97作為根節點,移到頂端,如圖2. 然后要對堆進行調整。比較此完全樹的根節點與其兩個子節點大小,因為27 < 38 < 97,所以27是三個節點里最小的,將節點27與根節點97交換。此時以97替代27而產生的右子樹為一個新的堆,再以97為根節點,對此最小堆進行調整,同理,知道要將97與49交換,得到圖3的完全樹。此時以97代替49為根節點的右子樹為一個新堆,再對此堆做同樣的操作,因為此完全樹已經是最小堆,所以可以停止操作,堆的調整完畢。此時再將根節點,對的最小值輸出,並進行同樣的調整,可以得到如圖4的新堆。這個過程被稱為“篩選”。

 

同樣以最小堆說明堆的初始化

  從一個無序序列初始化為一個堆的過程就是一個反復“篩選”的過程。由完全二叉樹的性質可以知,一個有n個節點的完全二叉樹的最后一個非葉節點是節點[n/2],堆的初始化過程就從這個[n/2]節點開始。上圖為如下無序數組的初始化:

    {49,38,65,97,76,13,27,50}

  首先,未處理的數組對應的堆為圖1模樣。從第四個節點開始([8/2]=4),因為50 < 97,故要交換兩節點,交換后還要繼續對其新的左子樹進行類似輸出后那樣的篩選。易見其左子樹只有節點97,已經為最佳情況,故可以繼續堆的初始化,如圖2。再考慮第三個節點,因為13 < 27 < 65,即節點13為當前的最小節點,故與節點65交換,並對新的左子樹進行篩選,其也為最佳情況,故可繼續堆的初始化,結果如圖3。然后考慮第二個節點,因為38 < 50 < 76,故已經為最優情況,不用調整。最后再考慮第一個節點,根節點。因為 13 < 38 < 49,故需要將根節點49與其右孩子節點13交換,交換后還要繼續對其新的右子樹進行類似輸出后那樣的篩選,可見右子樹還需要調整,因為 27 < 49 < 65,故將節點49與節點27交換。此時已經處理完了根節點,初始化結束。最終結果如圖5.

 

原文地址:http://www.cnblogs.com/wu8685/archive/2010/12/30/1922218.html


免責聲明!

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



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