上次说了个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