python实现堆排序(凑合着看吧)

1.前言:

在了解堆排序的过程时,首先要知道二叉树在列表中时怎么存储的,因为堆排序时基于完全二叉树的算法。

那么完全二叉树的父节点和子节点在列表中时什么关系呢

1.父节点找左节点的编号下标:i[子] = 2i[父] + 1

2.父节点找右节点的编号小标:i[子] = 2i[父] + 2

3.子节点找父节点:i[父亲] = (i[子] -1) // 2

3.用列表来存储二叉树,顺序从上到下,从左到右

2.堆排序中还要涉及到一个十分总要的算法,向下调整

1.思想:当根节点的左右子树都是堆的,可以通过一次向下的调整来将其变成一个堆

2.代码:

def shif(li, first, finaly):
    '''
    向下调整函数
    :param li: 列表
    :param first: 指向的是跟节点的小标
    :param finaly: 指向最后一个节点的下标
    :return:
    '''
    i = first   #i先指向根节点
    j = i * 2 +1    #j 先指向左节点
    count = li[first] # 用count存储待调整数的值
    while j <= finaly:  #当j大于最后一个元素的小标时,退出循环
        if j + 1 <= finaly and li[j + 1] > li[j]: #比较左右节点的大小,如果右节点大于左节点,则j指向右节点,同时要防止有右节点存在
            j = j + 1 #j指向右节点
        if li[j] > count: #比较子节点是否大于根节点
            li[i] = li[j] #如果大于,子节点上去
            i = j   #i指向已经空的位置
            j = 2 * i + 1 #j再次指向已经空的位置的左子节点
        else:
            li[i] = count #如果比他的子节点大则放到i这个位置
    else:
        li[i] = count #这里时说如果j已经超过了最后一个节点,那么count就放到了叶节点

3.那么堆排序的算法时啥呢:

1.建立堆:(农村包围城市)

1.1先看最后一个非叶子节点,先调整它

1.2然后看第二个非叶子几点,进行调整

1.3依次到的倒数第三层的时候,从最后一个节点进行调整,同时结合向下调整

1.4然后依次如此到根节点

2.得到堆顶元素为最大元素

3.去掉堆顶,将堆最后一个元素放到堆顶,此时有通过一个向下调整将它变成一个新的堆

4.堆顶有成为了这个新堆的最大元素

5.重复步骤3,直到堆变空

4.堆排序的实现代码

def shif(li, first, finaly):
    '''
    向下调整函数
    :param li: 列表
    :param first: 指向的是跟节点的小标
    :param finaly: 指向最后一个节点的下标
    :return:
    '''
    i = first   #i先指向根节点
    j = i * 2 +1    #j 先指向左节点
    count = li[first] # 用count存储待调整数的值
    while j <= finaly:  #当j大于最后一个元素的小标时,退出循环
        if j + 1 <= finaly and li[j + 1] > li[j]: #比较左右节点的大小,如果右节点大于左节点,则j指向右节点,同时要防止有右节点存在
            j = j + 1 #j指向右节点
        if li[j] > count: #比较子节点是否大于根节点
            li[i] = li[j] #如果大于,子节点上去
            i = j   #i指向已经空的位置
            j = 2 * i + 1 #j再次指向已经空的位置的左子节点
        else:
            li[i] = count #如果比他的子节点大则放到i这个位置
    else:
        li[i] = count #这里时说如果j已经超过了最后一个节点,那么count就放到了叶节点

def heap_sort(li):
    #先建立一个堆
    for i in range(((len(li)-1)-1)//2, -1, -1):
        shif(li, i, len(li)-1)
    #键堆完成
    #开始排序
    for i in range(len(li) - 1, -1, -1): #i表示堆的最后一个元素
        li[i], li[0] = li[0], li[i] #最后一个元素和第一个元素交换位置
        shif(li, 0, i-1) #i-1 表示的是新的finaly

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值