- 堆排序过程:
1.从下往上建堆,把每个小堆都向下调整为一个大根堆(sift),最后建立起一个完整的大根堆。
2. 从栈顶开始,将栈顶元素与最末元素交换(使最大元素在列表最末),然后将1~(n-1)的元素再向下调整(sift);重复操作,得到一个升序的序列;
- 堆排序代码:
# 堆的向下调整
def sift(alist,low,high):
'''
:param alist: 列表
:param low:堆得根节点位置
:param high:堆得最后一个元素位置
:return:list
'''
i=low #当前堆的根节点
j=2*i+1 #i的左孩子
tmp=alist[i] # 取出对顶元素
while j<=high:
if j+1<=high and alist[j+1]>alist[j]: # 若右孩子>左孩子,让j指向右孩子
j=j+1
if tmp<alist[j]:
alist[i]=alist[j]
i=j
j=2*i+1
else: # 不用调整
alist[i]=tmp
break
if j>high:
alist[i]=tmp # 将tmp放到叶子节点的位置
# 堆排序
def heap_sort(alist):
# 建堆,从最小堆开始
n=len(alist)-1
for i in range((n-1)//2,-1,-1): # 从孩子找父亲 i=(j-1)//2, 从最后一个父亲节点开始对当前子树进行排序
# i表示建立堆的时候调整部分子树的根节点
sift(alist,i,n)
# 挨个取堆顶元素
for j in range(n,-1,-1):
# j 一直指向堆的最后一个元素
alist[0],alist[j]=alist[j],alist[0]
sift(alist,0,j-1)
- python内置函数实现堆排序
# 内置函数实现堆排序
'''python内置模块:heapq
常用函数:
heapify(x)
heappush(heap,item) 加元素
heappop(heap)'''
import heapq
import random
alist=list(range(15))
random.shuffle(alist)
heapq.heapify(alist) # 建堆(小根堆)
new=[]
for i in range(15):
new.append(heapq.heappop(alist)) # 取出堆顶元素
- 堆排序适用场景:
- topk问题:找出前k大/小的数。(找出列表前k个数建立一个小根堆,然后将列表中剩下的元素与堆顶元素相比较,并且进行调整)O(nlogk)
# 堆的向下调整
def sift(alist,low,high):
'''
:param alist: 列表
:param low:堆得根节点位置
:param high:堆得最后一个元素位置
:return:list
'''
i=low #当前堆的根节点
j=2*i+1 #i的左孩子
tmp=alist[i] # 取出对顶元素
while j<=high:
if j+1<=high and alist[j+1]<alist[j]:
j=j+1
if tmp>alist[j]:
alist[i]=alist[j]
i=j
j=2*i+1
else: # 不用调整
alist[i]=tmp
break
if j>high:
alist[i]=tmp # 将tmp放到叶子节点的位置
# topk
def topk(alist,k):
# 建堆
heap=alist[:k]
for i in range((k-2)//2,-1,-1):
sift(heap,i,k-1)
# 遍历
for i in range(k,len(alist)-1):
if alist[i]>heap[0]:
heap[0]=alist[i]
sift(heap,0,k-1)
# 挨个取堆顶元素
for j in range(k-1, -1, -1):
heap[0], heap[j] = heap[j], heap[0]
sift(heap, 0, j - 1)
return heap