排序算法:堆排序

堆排序的时间复杂度为O(nlgn),由于堆是一个完全二叉树的形式,因此可以用数组来存储,通过下标的关系表示二叉树结点的父子、兄弟关系。

堆分为大顶堆以及小顶堆,以大顶堆为例。大顶堆的性质是每一个父节点的值都比孩子结点的值大,这是需要维护的最重要的性质。

在进行堆排序时,首先是将一个无序数组建成一个堆的形式,再将最后一个叶子结点和堆顶元素交换,得到最大值,然后从根结点开始向下维护堆性质,如此循环。

python实现:

 1 #堆排序算法
 2 def left(i) : #左孩子下标
 3     return(2 * i + 1)
 4 
 5 
 6 def right(i): #右孩子下标
 7     return(2 * i)
 8 
 9 
10 def MAX_HEAPIFY(A, i, end):  #维护堆的性质
11     l = left(i)
12     r = right(i)
13     heap_size = len(A)
14     if l < end and A[l] > A[i]: #保证当前父结点存在左孩子,找到三个结点中的最大值的下标
15         largest = l
16     else:
17         largest = i
18     if r < end and A[r] > A[largest]:
19         largest = r
20     if largest != i: #如果最大值的下标不是根节点,则交换两个值
21         A[largest], A[i] = A[i], A[largest]
22         MAX_HEAPIFY(A, largest, end) #以交换过的孩子结点的下标作为下一次的父结点,进行递归
23 
24 
25 def Build_max_heap(A): #将无序数组构建成为大顶堆
26     heap_size = len(A)
27     for i in range(heap_size//2, -1, -1): #从最后一个非叶子结点开始维护,逐个向上直到根节点
28         MAX_HEAPIFY(A, i, heap_size)
29 
30 
31 def Max_heap_sort(A): #堆排序算法
32     Build_max_heap(A) #先获得大顶堆
33     for i in range(len(A)-1, 0, -1):
34         A[i], A[0] = A[0], A[i] #将末尾结点和跟根节点交换
35         MAX_HEAPIFY(A, 0, i) #每交换一次,获得一个最大值,然后从根节点开始维护堆的性质
36                              #并去掉最后一个位置元素
37 
38 if __name__=='__main__':
39     list = [10, 6, 5, 8, 1, 2, 4, 9]
40     Max_heap_sort(list)
41     print(list)

结果为[1, 2, 4, 5, 6, 8, 9, 10]

这里要注意的是在MAX_HEAPIFY函数中加入结束时的下标,以此去掉数组结尾已经获得的排好序的部分。

posted @ 2019-10-10 22:09  小新要变成学霸  阅读(166)  评论(0编辑  收藏  举报