0
点赞
收藏
分享

微信扫一扫

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

程序猿不脱发2 2022-03-31 阅读 73
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
举报

相关推荐

0 条评论