python实现排序Nb三人组:快排、堆排序、归并排序

人之所以痛苦,那是因为你在成长。--------magic_guo

代码:
#排序中的Nb三人组:快排、归并排序、堆排序

# 排序中的Nb三人组:快排、归并排序、堆排序
li = [5, 7, 3, 1, 9, 4, 6, 13, 11, 16, 15, 19]

# 快排
def partition(li, left, right):
    tmp = li[left]
    while left < right:
        while left < right and li[right] >= tmp:
            right -= 1
        li[left] = li[right]
        while left < right and li[left] <= tmp:
            left += 1
        li[right] = li[left]
    li[left] = tmp
    return left


def quick_sort(li, left, right):
    if left < right:
        mid = partition(li, left, right)
        quick_sort(li, left, mid)
        quick_sort(li, mid+1, right)
    return li
# print(quick_sort(li, 0, len(li)-1))


# 归并排序
def merge(li, low, mid, high):
    ltmp = []
    i = low
    j = mid + 1
    while i <= mid and j <= high:
        if li[i] < li[j]:
            ltmp.append(li[i])
            i += 1
        else:
            ltmp.append(li[j])
            j += 1
    while i <= mid:
        ltmp.append(li[i])
        i += 1
    while j <= high:
        ltmp.append(li[j])
        j += 1
    li[low:high+1] = ltmp
    return li

def merge_sort(li, low, high):
    if low < high:
        mid = (low + high) // 2
        merge_sort(li, low, mid)
        merge_sort(li, mid+1, high)
        merge(li, low, mid, high)
    return li

# print(merge_sort(li, 0, len(li)-1))


# 堆排序
def sift(li, low, high):
    """
    向下调整函数
    :param li:列表
    :param low:堆顶
    :param high:堆的最后一个元素的位置
    :return:
    """
    # 指向堆顶元素
    i = low
    # 指向其左子节点,如果一个根节点的下标为i,则其做子节点下标为2i+1,右子节点下标为2i+2;
    j = 2*i + 1
    # 暂存其堆顶元素的值
    tmp = li[low]
    # 循环条件,当j大于high时,则表明堆的元素已经操作完毕
    while j <= high:
        # 比较其左右子节点的大小,取出最大值
        if j+1 <= high and li[j+1] > li[j]:
            # 使j的指向变为左右节点中最大的那个
            j = j + 1
        # 拿出左右子节点中最大的值与暂存的堆顶元素作比较
        if li[j] > tmp:
            # 如果大于堆顶元素,则意味着最大子节点上位堆顶
            li[i] = li[j]
            # 改变i的指向为j
            i = j
            # 重定向j的指向
            j = 2*i + 1
        else:
            break
        li[i] = tmp

#     else:
#         # 如果最大的元素比tmp还小,则tmp作为此时i指向的根节点,然后终止循环
#         li[i] = tmp
#         break
# # 循环条件结束,总要把tmp的值赋给i指向的节点
# else:
#     li[i] = tmp


# 建堆与排序的函数
def heap_sort(li):
    n = len(li)
    # 一直父子节点的关系为:父节点为i,则左子节点为2*i+1,右子节点为2*i+2
    # 反向推理,则一直子节点为i,则其父节点为(i-1)//2
    # 此时子节点为n-1,则则其父节点为(n-2)//2
    for i in range((n-2)//2, -1, -1):
        # i代表了建堆的时候,调整的每个部分堆的父节点的位置
        # 到n-1,只是一个表示是一个最大范围,防止越界
        sift(li, i, n-1)
    print(li)
    # 在上面的过程中已经将堆建立好,我们建立的是一个大根堆

    # 接下来我们对堆进行排序
    # 此时的i表示堆的最后一个元素
    for i in range(n-1, -1, -1):
        # 因为每次调整完后,堆顶元素都是最大的,所以为了不浪费空间,直接将堆顶元素与最后一个与元素进行交换,再进行调整
        li[0], li[i] = li[i], li[0]
        # 因为i的位置已经成了最大元素的位置,因此我们做调整的时候,不必包括最后一个元素,所以i-1
        sift(li, 0, i-1)
    return li

import random
le = [i for i in range(100)]
random.shuffle(le)
print(le)
print(heap_sort(le))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值