排序总结(python)

一、排序 Low B三人组

1.1 冒泡

思想:
1> 每两个相邻的数,如果前面比后面大,则交换这两个数。
2> 一趟排序完成后,则无序区减少一个数,有序区增加一个数。
3> 代码关键点:趟、无序区范围
代码:

def bubble_sort(li):
    for i in range(len(li)-1):
        for j in range(len(li)-1-i):
            if li[j] > li[j+1]:
                li[j], li[j+1] = li[j+1], li[j]

改进,某一趟未交换则表示排序完成

def bubble_sort(li):
    for i in range(len(li)-1):
        exchage = False
        for j in range(len(li)-1-i):
            if li[j] > li[j+1]:
                li[j], li[j+1] = li[j+1], li[j]
                exchage = True
        if not exchage:
            return li
    return li

时间复杂度:
O(n2)。

  它是一种稳定的排序算法。(稳定是指如果数组里两个相等的数,那么排序前后这两个相等的数的相对位置保持不变。)

1.2 选择

思想:
1> 一趟排序记录最小的数,放到第一个位置
2> 再一趟排序记录列表无序区最小的数,放到第二个位置
3> ……
4> 算法关键点:有序区和无序区、无序区最小数的位置

代码:

def select_sort(li):
    for i in range(len(li)-1): # i是第几趟
        min_loc = i
        for j in range(i+1, len(li)):
            if li[j] < li[min_loc]:
                min_loc = j
        li[i], li[min_loc] = li[min_loc], li[i]
    return li

1.3 插入

思想:
1> 初始时⼿手⾥里里(有序区)只有⼀一张牌
2> 每次(从⽆无序区)摸⼀一张牌,插⼊入到⼿手⾥里里已 有牌的正确位

代码:

def insert_sort(li):
    for i in range(1, len(li)):
        tmp = li[i]  # 拿出i位置,空出来
        j = i - 1
        while j >= 0 and li[j] > tmp:
            li[j+1] = li[j]  # 填补空位
            j -= 1           # 下标左移
        li[j+1] = tmp        # 将i位置的值放在j+1
     return li

二、排序 NB 三人组

2.1 快排

思想:
1> 取一个元素p(第一个元素),使元素p归位;
2> 列表被p分成两部分,左边都比p小,右边都比p大;
3> 递归完成排序。

def partion(data, left, right):
    tmp = data[left]
    while left < right:
        while left < right and data[right] >= tmp:
            right -= 1
        data[left] = data[right]
        while left < right and data[left] <= tmp:
            left += 1
        data[right] = data[left]
    data[left] = tmp
    return left


def quick_sort(data, left, right):
    if left < right:
        mid = partion(data, left, right)
        quick_sort(data, left, mid-1)
        quick_sort(data, mid+1, right)

2.2 归并

思想
  一开始先把列表从中间划分成两个子列表,一直递归地把列表组划分成更小的子列表,直到子列表里面只有一个元素,才开始排序。
  排序的方法就是按照大小顺序合并两个列表,接着依次按照递归的返回顺序,不断地合并排好序的子列表,直到最后把整个列表的顺序排好。
代码

def merge(li, low, mid, high):  # (low,mid) (mid+1,high)
    i = low
    j = mid + 1
    ltmp = []
    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执行完,有一边没数
    while i <= mid:
        ltmp.append(li[i])
        i += 1
    while j <= high:
        ltmp.append(li[j])
        j += 1
    li[low:high+1] = ltmp


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)

2.3 堆排

思想
1.建⽴立堆。
2.得到堆顶元素,为最⼤大元素
3.去掉堆顶,将堆最后⼀一个元素放到堆顶,此时可通过⼀一次调整重新使堆有序。
4.堆顶元素为第⼆二⼤大元素。
5.重复步骤3,直到堆变空

代码

def sift(li, low, high):  # 调整
    i = low  # i最开始指向根节点,父亲层
    j = 2 * i + 1  # j开始是左孩子
    tmp = li[low]  # 把堆顶存起来
    while j <= high:  # 只要j位置有数
        if j + 1 <= high and li[j + 1] > li[j]:  # 如果右孩子有且比较大
            j = j + 1  # j指向右孩子
        if li[j] > tmp:
            li[i] = li[j]
            i = j  # 往下看一层
            j = 2 * i + 1
        else:  # tmp更大,把tmp放到i位置上
            li[i] = tmp
            break
    else:
        li[i] = tmp  # 把tmp放到叶子节点上

def heap_sort(li):
    n = len(li)
    for i in range((n - 2) // 2, -1, -1):  # 子找父 (i-1)//2, (n-1 -1)//2, n//2 -1, 遍历到0不包括-1
        # i表示建堆的时候调整的部分的根的下标
        sift(li, i, n - 1)
    # 建堆完成
    print("建堆完成li:{}".format(li))

    for i in range(n - 1, -1, -1):  # n-1开始到0
        # i指向当前堆的最后一个元素
        li[0], li[i] = li[i], li[0]
        sift(li, 0, i - 1)  # i-1是新的high
    print("逐个出数li:{}".format(li))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值