排序算法 python

冒泡排序

"""
O(n^2)
交换相邻元素,每轮都有一个最大的沉底
内部循环的每轮比较数量随着已经排好序的元素会减少


根据升序排序:
  冒泡排序随着外部循环
  数组左半部分待排序
  数组右半部分有序
"""
def bubble_sort(nums):
    for i in range(len(nums)-1):
        # 每轮有一个最大的沉到底部,因此下一轮需要遍历的数量会减少一个
        for j in range(1, len(nums)-i):  
            if nums[j-1] > nums[j]:
                nums[j-1], nums[j] = nums[j], nums[j-1]
    return

改进冒泡

"""
O(n^2)
当某一轮未进行元素交换,则停止冒泡
"""
def bubble_sort_exch(nums):
    exch = True
    i = 0

    while i < len(nums) - 1 and exch:
        exch = False
        for j in range(1, len(nums)-i):
            if nums[j-1] > nums[j]:
                exch = True
                nums[j-1], nums[j] = nums[j], nums[j-1]
        i += 1
    return

选择排序

"""
O(n^2)

左半部分有序
右半部分待排序
每轮挑选右半部分中最小的元素放入当前位置
"""
def choice_sort(nums):
    for i in range(len(nums)-1):
        min_index = i
        for j in range(i+1, len(nums)):
            if nums[min_index] > nums[j]:
                min_index = j
        nums[i], nums[min_index] = nums[min_index], nums[i]
    return

插入排序

"""
O(n^2)
# 拿出当前位置的元素,插入到数组左半部分的正确位置
# 将当前元素暂存起来,左半部分元素大于当前元素时,将该元素右
"""
def insert_sort(nums):
    for i in range(1, len(nums)):
        j = i
        current_num = nums[i]
        while j > 0 and nums[j-1] > current_num:  ### 
            nums[j] = nums[j-1]
            j -= 1

        nums[j] = current_num
    return

希尔排序(间隔h插入)

def shell_sort(nums):
    h = 1
    while 3*h < len(nums):
        h = 3 * h + 1

    while h > 0:
        # ===== 间隔为 h 的插入排序, 这段代码设定h为3 ====
        for i in range(h, len(nums)):
            tmp = nums[i]
            j = i
            while j > 0 and nums[j-h] > tmp:
                nums[j] = nums[j-h]
                j -= h
            nums[j] = tmp
        # ==============================
        h //= 3
    return

归并排序

分治

"""
O(nlogn)
一分为二,单独排序,排好序的进行归并,空间换时间
"""
def merge_sort(nums, low, high):
    # terminator
    if low >= high:
        return
    # prepare data, split subproblem
    mid = low + (high - low) // 2
    # drill down
    merge_sort(nums, low, mid)
    merge_sort(nums, mid+1, high)
    # merge subresult
    merge(nums, low, mid, high)
    # reverse if needed
    return

def merge(nums, lo, mid, hi): 
    # lo~mid 有序, mid+1~hi有序。合并有序数组
    aux = [0] * len(nums)
    aux[lo: hi+1] = nums[lo: hi+1]


    i, j = lo, mid+1
    for k in range(lo, hi+1):
        if i > mid:
            nums[k] = aux[j]
            j += 1
        elif j > hi:
            nums[k] = aux[i]
            i += 1
        elif aux[i] > aux[j]:
            nums[k] = aux[j]
            j += 1
        else:
            nums[k] = aux[i]
            i += 1
    return

快速排序

递归

"""
# O(nlogn),当切分元素不好时,会倾向O(n2)
# 
# 对于某个 j, alist[j]已经排定
# alist[low] 到 alist[j-1] 中所有元素 不大于 alist[j]
# alist[j+1] 到 alist[high] 中所有元素 不小于 alist[j]
# 在 初次调用快速排序 之前,可以对待排序数组进行shuffle,避免选取的切分元素不好
"""
def quick_sort(nums, low, high):
    # terminator
    if low >= high:
        return  
    # process current level    
    divide = parition(nums, low, high)
    # drill down 
    quick_sort(nums, low, divide-1)
    quick_sort(nums, divide+1, high)
    # reverse if needed
    return

def parition(nums, low, high):
    value = nums[low]
    i, j = low+1, high
    while i <= j:
        # alist[low] 到 alist[j-1] 中所有元素 不大于 alist[j]
        while i <= j and nums[i] <= value:
            i += 1
        # alist[j+1] 到 alist[high] 中所有元素 不小于 alist[j]
        while i <= j and nums[j] >= value:
            j -= 1
        if i > j:
            break
        nums[i], nums[j] = nums[j], nums[i]
        
    nums[j], nums[low] = nums[low], nums[j]
    return

三切分快速排序(针对有重复元素)

def quick_sort_3way(nums, lo, hi):
    # terminator
    if lo >= hi:
        return
    # process current level
    """
    # lt and gt 是 数组中重复元素的开始结束索引
    # 通过使用索引 i 和 value比较
    # 将小于 value 的值交换到数组左端
    # 将大于 value 的值交换到数组右端
    """
    lt, gt = lo, hi
    i = lo + 1
    value = nums[lo]  # 切分元素
    while i <= gt:
        if nums[i] < value:
            nums[i], nums[lt] = nums[lt], nums[i]
            lt += 1
            i += 1
        elif nums[i] > value:
            nums[i], nums[gt] = nums[gt], nums[i]
            # 交换到i索引处的元素不一定小于value,因此i没有变化
            gt -= 1
        elif nums[i] == value:
            i += 1
    # drill down
    quick_sort_3way(nums, lo, lt-1)
    quick_sort_3way(nums, gt+1, hi)
    # reverse if needed
    return

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值