堆排序

堆排序需要对二叉树有了解
堆排序的堆是一个大根堆的完全二叉树,小根堆是最小的数在堆顶,大根堆是最大的数在堆顶。
在这里插入图片描述
二叉树的存储,二叉树是存储在一个列表上的,他的父节点和左孩子节点与右孩子节点的位置关系如下图所示。
在这里插入图片描述
对于大根堆二叉树的排序,首先将堆顶的数放到最后,然后将最后面的数3放到堆顶,然后判断3是否大于8和7,小于,比较8和7 的大小,8>7,将8放到堆顶,3放到8的位置;然后比较3和6和5的大小,3小于6和5, 6>5, 将6放到3的位置,3放到6的位置;然后比较3和2和4的大小,4和3交换位置。至此,出最后一个数外,这是一个大根堆二叉树。然后重复前面的操作,将8和倒数第二个位置的数交换位置,循环前面操作,知道只有一个数。

def down_sift(list, low, hight):
    """
    low:指向堆顶
    hight:指向堆底
    """
    tmp = list[low]
    i = low
    j = 2*i + 1
    while(j<=hight):
        if(j + 1 <= hight and list[j]<list[j+1]):
            j = j + 1
        if(list[j]>tmp):
            list[i] = list[j]
            i = j
            j = 2*i + 1
        else:
            break
    
    list[i] = tmp

二、怎么将一个不是大根堆的二叉树变成大根堆
我们从最后一个非叶子节点开始,也就是下图的3, 调用上面写的函数,low=(n-2)//2,high=n-1,进行一次调整,可以将5和3调换位置,此时的5和3便构成一个局部的大根堆,low向上移动,指向8,调用上面写的函数便可以实现8下面的数构成一个更大的局部大根堆,直至low指向堆顶,整个大根堆便建立完成。最后再调用大根堆排序算法就可以排序。
在这里插入图片描述

def heap_sort(list):
    n = len(list) 
    for i in range((n-2)//2,-1,-1):
        down_sift(list,i,n-1)

    hight = n-1
    while(hight >= 0):
        tmp = list[0]
        list[0] = list[hight]
        list[hight] = tmp
        down_sift(list,0,hight-1)
        hight = hight - 1
    
    return list

完整代码如下

def down_sift(list, low, hight):
    """
    low:指向堆顶
    hight:指向堆底
    """
    tmp = list[low]
    i = low
    j = 2*i + 1
    while(j<=hight):
        if(j + 1 <= hight and list[j]<list[j+1]):
            j = j + 1
        if(list[j]>tmp):
            list[i] = list[j]
            i = j
            j = 2*i + 1
        else:
            break
    
    list[i] = tmp
    

def heap_sort(list):
    n = len(list) 
    for i in range((n-2)//2,-1,-1):
        down_sift(list,i,n-1)

    hight = n-1
    while(hight >= 0):
        tmp = list[0]
        list[0] = list[hight]
        list[hight] = tmp
        down_sift(list,0,hight-1)
        hight = hight - 1
    
    return list

list = [i for i in range(10)]

import random
random.shuffle(list)
print(list)
heap_sort(list)
print(list)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值