- 前面了解了堆概念,接下来看下堆排序的思想:(以大根堆为例):
step1: 首先将待排序的数组构造出一个大根堆
step2: 取出这个大根堆的堆顶节点(最大值),与堆的最下最右的元素进行交换,然后把剩余的元素再构造一个大根堆
step3: 重复第二步,直到这个大根堆长度为1,完成排序 - 现在的关键问题是如何实现上述的算法,课本上直接使用了库函数,很方便,简洁,体现了python编程的优势,可以采用。但是我们想着自己整理一遍思路。
- 开始自己编写,首先待排序的数组是:
A = [50, 16, 30, 10, 60, 90, 2, 80, 70]
,二叉树表示如下图:
- 接下来执行step1,构造最大堆,调用我们已经设计的,上节课讲过的函数即可,结果是:
After heap, the list is [0, 90, 80, 50, 70, 60, 30, 2, 10, 16]
- 接下来执行step2,取出最大的,和最下最右的元素交换,为了方便就采用循环吧,记住从右到左,从下到上的顺序,交换之后的序列为:
After swap, the list is:[0, 16, 80, 50, 70, 60, 30, 2, 10, 90]
,最后一个元素可以从堆中删除了,然后堆剩余的元素The initial seq is [0, 16, 80, 50, 70, 60, 30, 2, 10]:
,此时堆成了这样子的:
对上面剩余的元素继续最大堆操作,序列为:Remain elements are build heap as:[0, 80, 70, 50, 16, 60, 30, 2, 10]
,对应图为:
- 接下来继续重复执行上面的step2,也就是把80和10交换,等等等等,就不用废话讲了吧,直到遍历完整个序列为止,最后输出的排序后的序列为:
[2, 10, 16, 30, 50, 60, 70, 80, 90]
- 上王道,代码的干活:
class BinHeap:
def __init__(self):
self.heapList = [0]
self.currentSize = 0
def max_heapify_rec(self, i):
if (i * 2) <= self.currentSize:
mc = self.maxChild(i)
if self.heapList[i] < self.heapList[mc]:
tmp = self.heapList[i]
self.heapList[i] = self.heapList[mc]
self.heapList[mc] = tmp
#print("%d-th -> %d-th node, seq is:%s" % (i, mc, self.heapList))
self.max_heapify_rec(mc)
def maxChild(self, i):
leftchild = i * 2
rightchild = i * 2 + 1
if leftchild <= self.currentSize and self.heapList[leftchild] > self.heapList[i]:
largest = leftchild
else:
largest = i
if rightchild <= self.currentSize and self.heapList[rightchild] > self.heapList[largest]:
largest = rightchild
return largest
def buildHeap(self, alist):
mid = len(alist) // 2
self.currentSize = len(alist)
self.heapList = [0] + alist[:]
print("The initial seq is %s:" % self.heapList)
while (mid > 0):
self.max_heapify_rec(mid)
mid = mid - 1
return self
def heap_sort(A):
bh = BinHeap()
bh = bh.buildHeap(A) #把序列A调整为一个大根堆
temp = bh.heapList
print('After heap, the list is %s' % temp)
outlist = [] #存放删除的节点,其实就是排好序的序列了
for i in range(len(temp) - 1): #把堆顶元素和堆末尾的元素交换,然后把剩余的元素调整为一个大根堆
temp[1], temp[-1] = temp[-1], temp[1]
print('After swap, the list is:%s' % temp)
del temp[0] #删除开始的占位符0
outlist.append(temp[-1])
del temp[-1] #删除最后一个元素
bh = bh.buildHeap(temp)
temp = bh.heapList
print('Remain elements are build heap as:%s' % temp)
return reversed(outlist)
A = [50, 16, 30, 10, 60, 90, 2, 80, 70]
print(list(heap_sort(A)))
- 还有比较新颖的做法,思路一样一样滴,就不废话了,上王道:
from collections import deque
def swap_param(L, i, j):
L[i], L[j] = L[j], L[i]
return L
def heap_adjust(L, start, end):
temp = L[start]
i = start
j = 2 * i
while j <= end:
if (j < end) and (L[j] < L[j + 1]):
j += 1
if temp < L[j]:
L[i] = L[j]
i = j
j = 2 * i
else:
break
L[i] = temp
def heap_sort(L):
L_length = len(L) - 1
first_sort_count = L_length / 2
for i in range(first_sort_count):
heap_adjust(L, first_sort_count - i, L_length)
for i in range(L_length - 1):
L = swap_param(L, 1, L_length - i)
heap_adjust(L, 1, L_length - i - 1)
return [L[i] for i in range(1, len(L))]
def main():
L = deque([50, 16, 30, 10, 60, 90, 2, 80, 70])
L.appendleft(0)
print heap_sort(L)
if __name__ == '__main__':
main()
- 教材上也有个好玩的,用库函数实现,看起来超级简单:
import heapq
def heapsort(alist):
sortedh = []
heapify(alist)
while alist:
sortedh.append(heappop(alist))
return sortedh
from heapq import heappop, heapify
A = [90, 50, 80, 16, 30, 60, 70, 10, 2]
K = heapsort(A)
print(K)
10.总结:实现一个功能要多想想算法的思路,思路正确,代码写出来还是比较简单的,博客上面备课太累了,要写太多东东了,以后继续坚持把,虽然浪费时间,但是对大家学习应该很有帮助,这个比PPT应该实用多了。