数据结构:堆排序

本节介绍了堆排序的定义、如何判断大根堆小根堆、堆排序的主要步骤、运行过程图解以及代码展现。

 

#堆排序(以大根堆为例):主要就是两个步骤:建立初始堆;出堆顶元素调整堆 两步
#建立初始堆:
#主要思想:堆+堆还是堆
#操作步骤:每个叶子结点都是一个堆,找到最后一个双亲结点,调整这个双亲结点和其下叶子结点(之后变成孩子结点,要一直遍历到叶子结点或者已经堆化就不要在继续),使其成为一个大根堆,
#然后再依据其层次遍历的序号,调整前一个结点,使其成为大根堆……
#出堆顶元素调整堆:
#主要步骤:出堆顶元素,找到按层次遍历序列得到的最后一个元素,把这个元素放到堆顶,从上往下调整(如果其孩子结点比根节点大,那么把两个孩子结点中最大的那个与根节点交换),直到无法调整
#或者到了叶子结点

#两个步骤的重点操作:根节点与孩子结点的比较与后移,这个操作叫做筛选
#建立初始堆就是从最后一个双亲结点往上,对每一个双亲结点进行筛选
#调整堆就是出堆顶,把最后一个元素放到堆顶,从上往下对所有结点进行筛选

#以下代码以根节点标号为0,且要调整为大根堆为例
#筛选算法
def siftDown(R,low,high):#R是列表,low是要堆化的双亲结点,high是这个列表最后的结点标号
    i=low
    j=2*i+1#用j来表示i的左孩子结点
    tmp=R[i]#用来临时存放要堆化的双亲结点的值
    while j<=high:#没有超过范围

        if j<high and R[j]<R[j+1]:#左孩子结点<high,给右孩子结点留了一个空间;若右孩子结点大于左孩子结点
            j+=1#把j指向大的那个右孩子结点
        #这两行代码之后j就指向了值较大的孩子结点的序号

        if tmp<R[j]:#因为要调整成大根堆,理应大的在上小的在下,如果出现双亲结点要小的情况,就i要交换调整
            R[i]=R[j]#把大的值赋值给双亲结点
            i,j=j,2*i+1#对ij重新赋值
        else:break#如果大的在上小的在下说明是大根堆,不要再调整了,退出while循环
    R[i]=tmp#原根节点放入最终位置,我也不太理解这里,我认为这个完全可以重新建一个表去放
    #这里这样做可能是为了节省空间实现原地排序,把大的统一放在线性表的最后

def SetHeap():#一般这个不单独列出来一个函数,就两行,需要用的话直接建就行
    for i in range(n//2-1,-1,-1):#n//2-1是根节点为1的最后一个双亲结点的序号
        siftDown(R,i,n-1)

def HeapSort(R):
    n=len(R)
    #形成初始堆
    for i in range(n//2-1,-1,-1):
        siftDown(R,i,n-1)
    #堆顶出堆,放在最后,不断调整,最后一个放到堆顶,然后进行排序
    for i in range(n-1,0,-1):
        R[0],R[i]=R[i],R[0]#
        siftDown(R,0,i-1)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

踏歌~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值