Heap
堆的定义如下:
具有n个元素的序列
(
h
1
,
h
2
,
.
.
.
,
h
n
)
(h_1, h_2, ..., h_n)
(h1,h2,...,hn),当且仅当满足
{
h
i
≥
h
2
i
h
i
≥
h
2
i
+
1
\left\{ \begin{array}{lr} h_i \geq h_{2i} \\ h_i\geq h_{2i+1} & \end{array} \right.
{hi≥h2ihi≥h2i+1
或者
{
h
i
≤
h
2
i
h
i
≤
h
2
i
+
1
\left\{ \begin{array}{lr} h_i \leq h_{2i} \\ h_i\leq h_{2i+1} & \end{array} \right.
{hi≤h2ihi≤h2i+1
(
i
=
1
,
2
,
⋯
,
n
2
)
(i=1, 2,\cdots, \dfrac{n}{2})
(i=1,2,⋯,2n)时称之为堆。本文讨论满足前者条件的堆。
在实际处理中,可以用一维数组
H
(
1
:
n
)
H(1: n)
H(1:n)来存储堆序列中的元素,也可以用完全二叉树来直观的表示堆的结构。例如,序列(50, 45, 40, 20, 25, 35, 30, 10, 15)是一个堆,它所对应的完全二叉树如图1所示。
图1 堆顶元素为最大项的堆
由图1可以看出,在用完全二叉树表示堆时,树中所有非叶子节点值均不小于其左、右子树的根节点值,因此,堆顶(完全二叉树的根节点)元素必为序列的n个元素中的最大项。
调整建堆(heap adjust)
在调整建堆的过程中,总是将根节点值与左、右子树的根节点值进行比较,若不满足堆的条件,则将左、右子树根节点值中的大者与根节点值进行交换。这个调整过程一直做到所有子树均为堆为止。
有了调整建堆的算法后,就可以将一个无序序列建成为堆。
假设无序序列
H
(
1
:
n
)
H(1:n)
H(1:n)以完全二叉树表示。从完全二叉树的最后一个非叶子节点(即第n/2个元素)开始,直到根节点(即第一个元素)为止,对每一个节点进行调整建堆,最后就可以得到与该序列对应的堆。
堆排序
根据堆的定义,可以得到堆排序的方法如下:
- 首先将一个无序序列建成堆。
- 然后将堆顶元素(序列中的最大项)与序列中最后一个元素交换(升序排列,最大项应该在序列的最后)。不考虑已经换到最后的那个元素,只考虑前
n
−
1
n-1
n−1个元素构成的子序列,显然,该子序列已经不是堆,但左、右子树仍为堆,可以将该自序列调整为堆。
反复做第2步,直到剩下的子序列为空为止。
图2 堆排序算法
堆排序的方法对于规模较小的线性表并不适用,但对于较大规模的线性表来说是很有效的。在最坏的情况下,堆排序需要比较的次数为
O
(
n
l
o
g
2
n
)
O(nlog_2n)
O(nlog2n)。在最坏情况下时间复杂度最小的排序法是堆排序。
堆排序算法的Python程序实现
def HeapSort(input_list):
#调整parent结点为最大堆
def HeapAdjust(input_list,parent,length):
temp = input_list[parent]
child = 2*parent+1
while child < length:
if child+1 <length and input_list[child] < input_list[child+1]:
child +=1
if temp > input_list[child]:
break
input_list[parent] = input_list[child]
parent = child
child = 2*child+1
input_list[parent] = temp
if input_list == []:
return []
sorted_list = input_list
length = len(sorted_list)
#最后一个结点的下标为length//2-1
#建立初始最大堆
for i in range(0,length // 2 )[::-1]:
HeapAdjust(sorted_list,i,length)
for j in range(1,length)[::-1]:
#把堆顶元素即第一大的元素与最后一个元素互换位置
temp = sorted_list[j]
sorted_list[j] = sorted_list[0]
sorted_list[0] = temp
#换完位置之后将剩余的元素重新调整成大根堆
HeapAdjust(sorted_list,0,j)
print('%dth' % (length - j))
print(sorted_list)
return sorted_list
if __name__ == '__main__':
input_list = [50,123,543,187,49,30,0,2,11,100]
print("input_list:")
print(input_list)
sorted_list = HeapSort(input_list)
print("sorted_list:")
print(input_list)
参考文献:
排序算法之python堆排序 https://blog.csdn.net/lerry13579/article/details/82052429