堆排序从理解到应用

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. {hih2ihih2i+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. {hih2ihih2i+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个元素)开始,直到根节点(即第一个元素)为止,对每一个节点进行调整建堆,最后就可以得到与该序列对应的堆。

堆排序

根据堆的定义,可以得到堆排序的方法如下:

  1. 首先将一个无序序列建成堆。
  2. 然后将堆顶元素(序列中的最大项)与序列中最后一个元素交换(升序排列,最大项应该在序列的最后)。不考虑已经换到最后的那个元素,只考虑前 n − 1 n-1 n1个元素构成的子序列,显然,该子序列已经不是堆,但左、右子树仍为堆,可以将该自序列调整为堆。
    反复做第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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gallant Hu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值