python排序题总结


冒泡排序 O(n^2)

遍历两轮,每两个前后比较,大的放到后面。exchange:当一轮中一次都没有交换的时候提前结束遍历。

def bubble_sort(self, li):  # 冒泡排序
    for i in range(len(li)):
        exchange = False
        for j in range(len(li) - i - 1):
            if li[j] > li[j+1]:
                li[j], li[j+1] = li[j+1], li[j]
                exchange = True
        if not exchange:
            return li

选择排序O(n^2)

遍历,选择最小的,放到列表第一个,以此类推。

def select_sort_simple(self, li):  # 选择排序
    li_new = []
    for i in range(len(li)):
        min_val = min(li)
        li_new.append(min_val)
        li.remove(min_val)
    return li_new

插入排序 O(n^2)

遍历,从头把依次将小的值插入到大的值前面。

def insort_sort(self, li):  # 插入排序
    for i in range(1, len(li)):
        tmp = li[i]
        j = i - 1
        while j >= 0 and li[j] > tmp:
            li[j+1] = li[j]
            j -= 1
        li[j+1] = tmp
        return li

快速排序O(nlogn)

找到中间值,小的都放该值左边,大的都放右边。递归。
先选取最左边的值为tmp, right只要比tmp大就左移直到找到比tmp小的,把right的值给left, left同理,left把当前值给right, 然后tmp把值给到当前的left。

def quick_sort(self, li, left, right):  # 快速排序
   if left < right:
       mid = self.partition(li, left, right)
       self.quick_sort(li, left, mid)
       self.quick_sort(li, mid + 1, right)
   return li

def partition(self, 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

归并排序O(nlogn

先分再合,合的时候把小的放前面。li[low: high + 1] = res 里面+1是因为顾前不顾后。

def merge_sort(self, li, low, high):  # 归并
    if low < high:
        mid = (low + high) // 2
        self.merge_sort(li, low, mid)
        self.merge_sort(li, mid + 1, high)
        self.merge(li, low, mid, high)
    return li

def merge(self, li, low, mid, high):
    res = []
    i = low
    j = mid + 1
    while i <= mid and j <= high:
        if li[i] <= li[j]:
            res.append(li[i])
            i += 1
        else:
            res.append(li[j])
            j += 1
    while i <= mid:
        res.append(li[i])
        i += 1
    while j <= high:
        res.append(li[j])
        j += 1
    li[low: high + 1] = res

希尔排序

按一个区间不断排序,不断缩小区间。

def shell_sort(self, li):
    d = len(li) // 2
    while d > 1:
        self.insert_sort_gap(li, d)
        d = d // 2
    return li

def insert_sort_gap(self, li, gap):
    for i in range(gap, len(li)):
        tmp = li[i]
        j = i - gap
        while j >= 0 and li[j] > tmp:
            li[j + gap] = li[j]
            j = j - gap
        li[j + gap] = tmp

计数排序O(n)

已知列表中的数范围在0到100之间。创建列表记录每个数字有几个,用enumerate把序号做了数字append到列表中。

def count_sort(li, max_count=100):
    count = [0 for _ in range(max_count + 1)]
    for val in li:  # val是序列里的值
        count[val] += 1
    li.clear()
    for val, ind in enumerate(count):  # 值为val的元素有ind个
        for i in range(ind):
            li.append(val)

桶排序

  • 元素范围较大时使用
  • 在按范围将元素放入不同的桶中,放进去的时候顺便排序。
def bucket_sort(li, n=100, max_num=10000):
    buckets = [[] for _ in range(n)]  # 创建桶
    for val in li:
        i = min(val // (max_num // n), n - 1)  # i表示val放到几号桶里
        buckets[i].append(val)
        # 可以全都放到桶里再排序,也可以放到桶里的过程中顺便排序
        # 这里选第二种
        for j in range(len(buckets[i]) - 1, 0, -1):  # 从后往前遍历
            if buckets[i][j] < buckets[i][j - 1]:
                buckets[i][j], buckets[i][j - 1] = buckets[i][j - 1], buckets[i][j]
            else:
                break
    sorted_li = []
    for buc in buckets:
        sorted_li.extend(buc)  # 连接列表
    return sorted_li

基数排序

根据数字的位数将列表里的数分为几部分,对这几部分分别进行排序(和桶排序差不多)

def radix_sort(li):
    max_num = max(li) # 最大值的位数
    it = 0 # 迭代次数
    while 10 ** it <= max_num:
        buckets = [[] for _ in range(10)]
        for val in li:
            digit = (val // 10 ** it) % 10
            buckets[digit].append(val)
        # 分桶完成
        li = []
        for buc in buckets:
            li.extend(buc)
        # 把数写回li
        it += 1
    return li
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值