构建大根堆
用数组模拟大根堆,规定第0的位置不存在数字,长度为len+1的数组,使用arr[1]~arr[len]来存储数字
from graphviz import Digraph
import os
def buildMaxHeap(arr,len):
# len//2表示,舍弃小数部分,向下取整
# len//2是非叶子节点,即,len//2是下表最大的父亲节点
for i in range(len//2,0,-1):
headAdjust(arr,i,len)
def displayHeap(arr,len):
os.environ['PATH'] = os.pathsep + r'D:\\Software\\Graphviz\\Graphviz-10.0.1-win64\\bin'
dot=Digraph()
for i in range(1,len+1):
dot.node(str(i),str(arr[i]))
if i!=1:
parent_index=i//2
dot.edge(str(parent_index),str(i))
dot.render("heap",format="png",view=True)
def headAdjust(arr,king,len):
# 求左儿子节点,此时son是左儿子的下标
son=2*king
while(son<=len):
# 左右儿子相比取最大值,
if son+1<=len and arr[son]<arr[son+1]:
# 此时,son是最大值的儿子下标
son=son+1
# 父亲节点的值比儿子节点的值都大,满足大根堆的要求,不必调整
if arr[king]>arr[son] :break
else :
# 儿子节点的值比父亲节点的值大,交换两个节点的数据
swap(arr,king,son)
# 父亲节点的旧的值被淘汰到儿子节点的位置
# 此时以儿子节点为父亲节点,继续检查它的儿子是否满足大根堆的要求
king=son
# 寻找儿子节点
son*=2
def swap(arr,i,j):
temp=arr[i]
arr[i]=arr[j]
arr[j]=temp
if __name__=="__main__":
# 第0位置,不存储数据
arr=[None]*9
len=8
arr=[None,53,17,78,9,45,65,87,32]
# [None, 87, 45, 78, 32, 17, 65, 53, 9]
buildMaxHeap(arr,len)
print(arr)
displayHeap(arr,len)
[None, 87, 45, 78, 32, 17, 65, 53, 9]
堆排序:
大根堆的特点就是最大的数字在数组的第1个位置,把数组的第1位置放到数组的最后位置,然后把数组的最后位置的数(已经排序好了) ,移除大根堆。接着在子数组中继续构建大根堆。
import random
import time
def heapSort(arr,len):
# 建立大跟堆,把最大的值放到arr[1]中
buildMaxHeap(arr,len)
for i in range(len,1,-1):
# 把最大值放到arr[i]末尾
swap(arr,1,i)
# 之后,arr[i]离开大根堆
# 建立大根堆,把子数组最大的数值放到arr[1]
HeadAjust(arr,1,i-1)
def buildMaxHeap(arr,len):
# 从最大的父亲节点开始,调整大根堆,把最大值放到arr[i]
for i in range(len//2,0,-1):
HeadAjust(arr,i,len)
def HeadAjust(arr,king ,len):
son=king*2
while(son<=len):
if (son+1<=len and arr[son]<arr[son+1]):
son=son+1
if arr[king]>arr[son]: break
else :
swap(arr,king,son)
king=son
son*=2
def swap(arr,i,j):
temp=arr[i]
arr[i]=arr[j]
arr[j]=temp
def test():
maxSize=11
arr=[None]*maxSize
len=maxSize-1
for i in range(1,len+1):
arr[i]=random.randint(0,99)
print(arr)
heapSort(arr,len)
print(arr)
def test2():
maxSize=50001
arr=[None]*maxSize
len=maxSize-1
for i in range(1,len+1):
arr[i]=random.randint(0,50000)
start=time.time()
print("start:",start)
heapSort(arr,len)
end=time.time()
print("end ", end)
print("cost:", (end-start)," seconds")
if __name__=="__main__":
# test()
test2()
test()
[None, 54, 98, 28, 57, 24, 37, 69, 57, 15, 9]
[None, 9, 15, 24, 28, 37, 54, 57, 57, 69, 98]
test2()
start: 1710660200.8720586
end 1710660201.0435638
cost: 0.17150521278381348 seconds