排序算法总结:
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:
- 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
- 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;
堆排序的平均时间复杂度为 Ο(nlogn)。
一般用数组来表示堆,下标为 i 的结点的父结点下标为(i-1)/2;其左右子结点分别为 (2i + 1)、(2i + 2)
在堆的数据结构中,堆中的最大值总是位于根节点(在优先队列中使用堆的话堆中的最小值位于根节点)。堆中定义以下几种操作:
① 最大堆调整(Max_Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点
② 创建最大堆(Build_Max_Heap):将堆所有数据重新排序
③ 堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算
在堆排序的时候,对于一个无序数组,首先是从最后一个分支开始,依次创建最大堆,根据刚才说的父节点与左右子节点在数组中的索引关系,那对于数组的最后一个节点,其父节点就是length//2-1,例如一个长度为7的数组[1,2,3,4,5,6,7],二叉树如下:
最后一个节点7的父节点的值为3,索引为2.
最开始调整的最小子树就是3 6 7这个部分,调整好后节点3与7互换,得到7 6 3,父节点向前移动一位,继续调整2 4 5这个节点,
直到父节点来到根节点并且调整完毕,这时根节点为最大值:
但是在调整过程中,下面子树可能会再次不满足最大堆的条件,例如上树中,1 6 3这个子树就变的又不是最大堆了,所以在调整时,要时刻关注交换后是否会对下面的子树造成影响,做法是定一个标志点flag,当其为0时,表示当前子树满足最大堆,没有调整;当其为1时,表示父节点和左孩子发生了交换,那此时就要顺着左孩子继续向下找,再次调整其为最大堆;当其为2时,表明父节点和右子树发生了交换,这时要顺着右子树向下找,再次调整右子树为最大堆。
最大堆创建好后,其根节点就是最大值,这时将根节点与最后一个节点交换,根节点就来到了数组的最后。交换后,固定最后一个值,再次调整前面为最大堆,然后再次交换,直到整个数组有序。
Python实现:
def heapSort(arr):
length = len(arr)
if length <= 1:
return
i = length//2-1
while i>=0:
# 构造最大堆
p, l, r = i, 2*i+1, 2*i+2
flag = creatMaxHeap(arr, length, p, l, r)
# 调整最大堆
if flag == 1:
adjustMaxHeap(arr, length, l)
elif flag == 2:
adjustMaxHeap(arr, length, r)
i -= 1
# 排序
end = length-1
while end >= 1:
arr[0], arr[end] = arr[end], arr[0]
p, l, r = 0, 1, 2
flag = creatMaxHeap(arr, end, p, l, r)
if flag == 1:
adjustMaxHeap(arr, end, l)
elif flag == 2:
adjustMaxHeap(arr, end, r)
end -= 1
def creatMaxHeap(arr, length, p, l, r):
flag = 0
if r<length:
if arr[l] >= arr[r]:
if arr[l] > arr[p]:
arr[p], arr[l] = arr[l], arr[p]
flag = 1
else:
if arr[r] > arr[p]:
arr[p], arr[r] = arr[r], arr[p]
flag = 2
elif l<length:
if arr[p] < arr[l]:
arr[p], arr[l] = arr[l], arr[p]
flag = 1
return flag
def adjustMaxHeap(arr, length, p):
l, r = 2*p+1, 2*p+2
while r<length:
flag = creatMaxHeap(arr, length, p, l ,r)
if flag == 1: p = l
elif flag == 2: p = r
else:break
l, r = 2*p+1, 2*p+2
if l < length:
if arr[l] > arr[p]:
arr[l], arr[p] = arr[p], arr[l]
arr = [47, 29, 71, 99, 78, 19, 24]
heapSort(arr)
print(arr)