关于堆排序的相关知识,在数据结构的排序算法中,堆排序可以说是一个比较难的算法,理解起来有点困难,所以要想掌握堆排序,得先了解一下几个数据结构:
首先,我们要知道完全二叉树,先看图:
完全二叉树:设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,
第 h 层所有的结点都连续集中在最左边
满二叉树:深度为k且有2^k-1个结点的二叉树称为满二叉树
知道了完全二叉树后,我们来了解堆:
堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:
- 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
- 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列
知道了相关知识后,我们来了解对排序的算法步骤和代码实现。
算法步骤:
代码实现:
def sift(li, low, high):
i = low
j = 2 * i + 1
tmp = li[i]
while j <= high:
if j < high and li[j] < li[j+1]:
j = j+1
if tmp < li[j]:
li[i] = li[j]
i = j
j = 2 * i + 1
else:
li[i] = tmp
break
else:
li[i] = tmp
def heap_sort(li):
n = len(li)
for i in range((n-2)//2,-1,-1):
sift(li,i,n-1)
#建堆完成了
for i in range(n-1,-1,-1):
# i指向堆的最后一个元素
li[0], li[i] = li[i], li[0]
# i-1指向新的high
sift(li, 0, i-1)
return li
其中sift函数使用来实现堆的调整过程,即节点每向上移动一次,都要用sift函数来确保依然是一个堆,虽然思想有点难,但是实现起来还是不难的
我们来实验一下:
import random
li = list(range(1000))
random.shuffle(li)
print(heap_sort(li))
运行结果:
可以看到,列表已经排好序了。