python 实现几大排序算法

1、插入排序

插入排序的思想是由后往前插入,选择合适的位置插入之后,进行下一个操作。
稳定算法,时间复杂度O(n^2),空间复杂度O(1)。图源百度
插入排序

def insert_sort(nums):
    for i in range(len(nums)):
        tmp = nums[i]
        j = i
        # 如果当前位数字比前位数字小,将前位数字后移
        while j >=1 and nums[j-1] > tmp:
            nums[j] = nums[j-1]
            j -= 1
        # 此时j之前的位置都小于当前位数字,j之后的位置都大于当前位数字,将数字插入
        nums[j] = tmp
    return nums

2、希尔排序

希尔排序和插入排序相似,只不过是插入排序每次只迈一步,希尔排序每次迈一大步,然后步子变小,最后步子变成1。
不稳定算法,时间复杂度O(n^1.3-2),空间复杂度O(1)。图源百度
在这里插入图片描述

def shell_sort(nums):
    gap = len(nums)//2
    while gap>0:
        # 每次走一大步,进行插入排序
        for i in range(gap,len(nums)):
            tmp = nums[i]
            j = i
            while j >= gap and nums[j-gap] > tmp:
                nums[j] = nums[j-gap]
                j -= gap
            nums[j] = tmp
        # 步数变小,直至1
        gap = gap//2
    return nums

3、基数排序

基数排序是非比较的排序方法,先根据个位数插入到对应的桶中,再展开;然后根据十位数再插入到桶中,再展开;直到最高位。注意只能用于自然数的排序,毕竟有小数了,你没法插到桶里去啊!自己画一个图!
稳定排序,时间复杂度O((n+r)*k),空间复杂度O(r×n)。(n个数,r个桶,最大k位数)
在这里插入图片描述

def radix_sort(nums):
    max_len = len(str(max(nums)))
    for i in range(max_len):
        # 分配10个桶
        bucket_list = [[] for _ in range(10)]
        for j in nums:
            # 放到每个桶中
            bucket_list[j//(10**i)%10].append(j)
        # 展开
        nums = [q for p in bucket_list for q in p]
    return nums

4、冒泡排序

冒泡排序是每次找到最大(或最小)的数字,放在开头或者结尾。之所以叫冒泡的意思是泡泡是逐渐变大的过程。
稳定排序,时间复杂度O(n^2),空间复杂度O(1)

def bubble_sort(nums):
    for i in range(len(nums)):
        for j in range(1,len(nums)-i):
        	# 找到大的数字然后交换
            if nums[j] < nums[j-1]:
                nums[j],nums[j-1] = nums[j-1],nums[j]
    return nums

5、归并排序

归并排序是分治的思想,将序列拆成两份、四份、八份,,,最后直到长度为1的有序数列,然后再进行合并。
稳定排序,复杂度O(nlogn),空间复杂度O(n)。

def merge(nums,l,mid,r):
    # 分配空间
    tmp = [0]*(r-l+1)
    k = 0
    i = l
    j = mid+1
    # 合并两个有序数列
    while i<=mid and j<=r:
        if nums[i] < nums[j]:
            tmp[k] = nums[i]
            k += 1
            i += 1
        else:
            tmp[k] = nums[j]
            k += 1
            j += 1
    # 如果左边数列未合并完
    while i <= mid:
        tmp[k] = nums[i]
        k += 1
        i += 1
     # 如果右边数列未合并完
    while j <= r:
        tmp[k] = nums[j]
        k += 1
        j += 1
    nums[l:r+1] = tmp[:]
    return nums

def merge_sort(nums,l,r):
    if l < r:
        # 找到断开点
        mid = int(l+r)//2
        # 递归
        nums = merge_sort(nums,l,mid)
        nums = merge_sort(nums,mid+1,r)
        # 合并
        nums = merge(nums,l,mid,r)
    return nums

6、堆排序

堆排序是利用二叉树,将大的数字放在根结点(大顶堆),每次取出根结点之后重新调整堆,直至堆为空。
不稳定排序,时间复杂度O(nlogn),建堆时间O(n),空间复杂度O(1)

def heapify(nums,n,i):
    large = i
    l = 2 * i + 1 # 左节点
    r = 2 * i + 2 # 右节点
    if l < n and nums[large] < nums[l]: # 往左节点走
        large = l
    if r < n and nums[large] < nums[r]: # 往右节点走
        large = r
    if large != i:
        # 调整根结点和子节点的大小
        nums[i],nums[large] = nums[large],nums[i]
        # 当跟节点的值变化时,调整改变节点的堆(不一定是大顶堆)
        heapify(nums,n,large)
def heap_sort(nums):
    n = len(nums)
    for i in range(n,-1,-1):
        # n是长度,i是节点序号,保证每一个节点都是大顶堆
        heapify(nums,n,i)
    # 最大数在根结点
    for i in range(n-1,-1,-1):
        # 取出根结点之后放在最后的位置,将最后位置值调到根结点
        nums[i],nums[0] = nums[0],nums[i]
        # 调整堆
        heapify(nums,i,0)
    return nums

7、桶排序

桶排序就是将数据划分成几个大小区间,然后再进行排序,可以同其它排序想结合。
稳定性取决于桶内算法的稳定性,空间复杂度和时间复杂度同样受桶内排序算法的影响。

def bucket_sort(nums):
    max_num = nums[0]
    min_num = nums[0]
    for i in nums:
        if max_num < i:
            max_num = i
        if min_num > i:
            min_num = i
    # 根据最大值、最小值划分桶的个数
    bucket_num = int((max_num - min_num)/len(nums)) + 1
    bucket = [ [] for _ in range(bucket_num)]
    for i in range(len(nums)):
        bucket[int((nums[i] - min_num)/len(nums))].append(nums[i])
    # 在每个桶内进行排序
    for i in range(bucket_num):
        # 偷懒,直接sort排序
        bucket[i].sort()
    k = 0
    for i in range(bucket_num):
        for val in bucket[i]:
            nums[k] = val
            k += 1
    return nums

8、快速排序

快排是思路是将小于当前位的数字放在左边,大于当前位的数字放在右边,是比较算法里面最高效的算法。
不稳定、时间复杂度O(nlogn),空间复杂度O(1)。图源百度
在这里插入图片描述

def quick_sort(nums,left,right):
    if left >= right:
        return nums
    # 取左边作为当前位的值
    tmp = nums[left]
    i = left
    j = right
    while i!=j:
        # 如果右边的值比当前位大,右指针左移
        while i<j and nums[j] >= tmp:
            j -= 1
        # 当右边的值比当前位小的时候,交换值
        nums[i],nums[j] = nums[j],nums[i]
        # 如果左边的值比当前位小,左指针右移
        while i<j and nums[i] <= tmp:
            i += 1
        # 当左边的值比当前位大的时候,交换值
        nums[i],nums[j] = nums[j],nums[i]
    # 对左、右边进行排序
    nums = quick_sort(nums,i+1,right)
    nums = quick_sort(nums,left,i-1)
    return nums

好了全部写完了,小伙伴们要记得动手哦!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值