Python实现堆排序

构建大根堆

用数组模拟大根堆,规定第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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值