上次說了個Huffman編碼,此次說說堆排序,先貼Python代碼:python
class MaxHeap: arrInfo = [] heapSize = 0 def __init__(self): self.initArr() def initArr(self): self.arrInfo = [0]+[4,12,32,54,2,54,34,76,34,87] self.heapSize = len(self.arrInfo)-1 def maxHeapify(self,index): l = self.leftIndex(index) r = self.rightIndex(index) largest = index if l <= self.heapSize and self.arrInfo[l] > self.arrInfo[index]: largest = l if r <= self.heapSize and self.arrInfo[r] > self.arrInfo[largest]: largest = r if largest != index: ln = self.arrInfo[largest] self.arrInfo[largest] = self.arrInfo[index] self.arrInfo[index] = ln self.maxHeapify(largest) def buildMaxHeap(self): for i in range(self.heapSize/2,0,-1): self.maxHeapify(i) def heapSort(self): self.buildMaxHeap() for i in range(self.heapSize,1,-1): a1 = self.arrInfo[1] self.arrInfo[1] = self.arrInfo[i] self.arrInfo[i] = a1 self.heapSize -= 1 self.maxHeapify(1) def leftIndex(self,index): return index*2 def rightIndex(self,index): return index*2+1 def printResult(self): print self.arrInfo[1:] self.heapSort() print self.arrInfo[1:] MaxHeap().printResult()
第一步初始化數組,有點特別的地方,就是不包含第一個元素,由於數組的索引是從0開始,而排序時,堆的根節點編號應該置爲1,這樣好計算指定節點的左右孩子(其實從0編號,也能夠算,可是繁瑣一點),若是編號爲0,那麼根據上述簡單的計算方法(該計算方法是比較符合二叉樹的特性的),能夠得出左右孩子的編號分別爲:0和1,這顯然是不對的,可是若是根節點編號爲1,計算結果爲:2和3,很是正確。api
第二步提供一個maxHeapify方法,該方法也比較簡單,若是發現子節點比父節點的值大,則進行交換,再遞歸執行下去。如若對某個節點(存在子節點)調用該方法,不能保證該節點的值必定大於左右節點的值(這個要注意,否則就曲解了該方法的意義了),可是必定能夠實現該方法遞歸調用的最後一次的那個父節點的值大於左右節點的值。因此該方法的調用,須要使用一種自下而上的調用,且看第三步。數組
第三步就要構造一個最大堆(父節點的值必定都大於子節點的值,但不是排好序的),buildMaxHeap自下而上的調用maxHeapify方法。最上層固然是根了,這裏的最下層是最後一個包含子節點的節點(根據二叉樹的特性,該節點的編號就應該是length/2,length爲堆的大小,也就是二叉樹的總節點個數,這裏Python會自動只取整數部分)。那麼自下而上調用,就是從最下面的那個節點到最上面的根節點,依次調用maxHeapify方法,這樣一個最大堆就構造好了,保證了全部的父節點的值必定是大於子節點的了。ui
第四步就是排序了。這步比較有意思,基於上面的最大堆,根節點元素是堆中最大的。將根節點與最後一個節點交換,而後去除最後一個節點(堆的大小就減一,而且該節點是堆中最大的),對根節點(新的根節點)再調用maxHeapify方法(這裏調用完後會保證全部的父節點的值必定大於子節點的值,因此根節點就是堆中最大的值,這裏要好好悟),遞歸下去,排序就完成了。編碼
堆排序就囉嗦完了,美中不足的就是缺乏圖文並茂的描述,太多的文字也許會看的迷糊,可是原生態的,沒那麼多精力去整圖了,spa