[算法]用Python实现十大排序算法

1. 冒泡排序

给定一串数组,里面的较大值一个接一个地流向尾部

def bubbleSort(arr):
    for i in range(len(arr)):
        j = 0
        while j < len(arr) - i - 1:
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
            j += 1

优化版本,即能够探测到前置部分已有序,终点前移

def bubbleSort(arr):
    n=len(arr)-1
    while n>0:
        j,end= 0,0
        while j < n:
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
                end= j
            j += 1
        n=end

2. 选择排序

每次从待排序数组中拿出最大的放到后面去

def selectSort(arr):
    for i in range(len(arr), 0, -1):
        maxIdx = 0
        for j in range(i):
            if arr[maxIdx] < arr[j]:
                maxIdx = j
        arr[maxIdx], arr[i - 1] = arr[i - 1], arr[maxIdx]

3. 插入排序

从头遍历数组,每次把当前位置的值插入到前面有序队列中

def insertSort(arr):
    for i in range(1, len(arr)):
        val, j = arr[i], i - 1
        while j >= 0 and val < arr[j]:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = val

4. 希尔排序

利用间隔将数组拆分,比如数组[0,1,2,3,4,5,6,7],按照间隔4拆分为4个子集[0,4]、[1,5]、[2,6]、[3,7]分别进行插入排序,之后再利用间隔2拆分成2个子集分别进行插入排序,再利用间隔1即本身插入排序。

def shellSort(arr):
    s = len(arr) // 2
    while s > 0:
        for i in range(0, s):
            for j in range(i + s, len(arr), s):
                val, k = arr[j], j - s
                while k >= 0 and val < arr[k]:
                    arr[k + s] = arr[k]
                    k -= s
                arr[k + s] = val
        s //= 2

为了体现出和插入排序的关联,对3.插入排序加入了起点和间隔控制,嵌入到希尔排序中如下

def insertSort(arr, start, interval):
    for i in range(start, len(arr)):
        val, j = arr[i], i - interval
        while j >= 0 and val < arr[j]:
            arr[j + interval] = arr[j]
            j -= interval
        arr[j + interval] = val

def shellSort(arr):
    s = len(arr) // 2
    while s > 0:
        for i in range(0, s):
            insertSort(arr, i + s, s)
        s //= 2

5. 归并排序

有序数组 = 有序子数组1 + 有序子数组2

def mergeSort(arr):
    subMergeSort(arr, 0, len(arr))

def subMergeSort(arr, left, right):
    if left >= right - 1:
        return
    mid = left + (right - left) // 2
    subMergeSort(arr, left, mid)
    subMergeSort(arr, mid, right)
    tmp = arr[left:mid]
    idx = 0
    while idx < len(tmp):
        if mid == right or tmp[idx] <= arr[mid]:
            arr[left] = tmp[idx]
            idx += 1
        else:
            arr[left] = arr[mid]
            mid += 1
        left += 1

6. 快速排序

将元素放到本应该有序的正确位置,即左边的都小于等于自己,右边的都大于自己

def quickSort(arr):
    subQuickSort(arr, 0, len(arr))

def subQuickSort(arr, left, right):
    if left >= right:
        return
    val = arr[left]
    low, idx = left + 1, left + 1
    while idx < right:
        if val >= arr[idx]:
            arr[low], arr[idx] = arr[idx], arr[low]
            low += 1
        idx += 1
    arr[low - 1], arr[left] = arr[left], arr[low - 1]
    subQuickSort(arr, left, low - 1)
    subQuickSort(arr, low, right)

7. 堆排序

首先构造堆,之后不断从堆顶取出即可

import copy

class Myheap:
    def __init__(self, arr):
        self.arr = copy.deepcopy(arr)
        self.len = len(arr)
        self.heapSort()

    def heapSort(self):
        idx = 0
        for i in range(self.len // 2, -1, -1):
            self.downAdjust(i)
            idx += 1

    def downAdjust(self, pos):
        left = pos * 2 + 1
        val = self.arr[pos]
        while left < self.len:
            if left + 1 < self.len and self.arr[left] > self.arr[left + 1]:
                left = left + 1
            if val <= self.arr[left]:
                self.arr[pos] = val
                return
            self.arr[pos] = self.arr[left]
            pos = left
            left = pos * 2 + 1
        self.arr[pos] = val

    def headPop(self):
        val, self.arr[0] = self.arr[0], self.arr[-1]
        self.arr = self.arr[:-1]
        self.len -= 1
        if self.len > 0:
            self.downAdjust(0)
        return val

def heapSort(arr):
    h = Myheap(arr)
    res = []
    while h.len > 0:
        res.append(h.headPop())
    return res

8. 计数排序

统计元素出现的次数

def countSort(arr):
    res = list()
    if len(arr) == 0:
        return res
    maxV, minV = max(arr), min(arr)
    tmp = [0] * (maxV - minV + 1)
    print(tmp)
    for v in arr:
        tmp[v - minV] += 1
    for idx, v in enumerate(tmp):
        res += [idx + minV] * v
    return res

9. 桶排序

将元素分布到不同的桶里面(可以利用hash,这里为了方便有点类似计数排序),之后每个桶分别排序,最后可以归并(这里因为分配算法最后结果有序,就没有归并)

#k表示每个桶的最大容量
def bucketSort(arr, k):
    res = list()
    if len(arr) == 0:
        return res
    maxV, minV = max(arr), min(arr)
    tmp = [[] for _ in range(((maxV - minV) // k + 1))]
    for v in arr:
        tmp[(v - minV) // k].append(v)
    for idx, v in enumerate(tmp):
        r = sorted(v)
        res += r
    return res

10. 基数排序

# k表示十进制的最大位数
def radixSort(arr):
    maxV = max(arr)
    k = 1
    tmp = maxV
    while tmp // 10:
        tmp //= 10
        tmp += 1
    tmp = [[] for _ in range(10)]
    for i in range(k):
        for j in arr:
            idx = j // (pow(10, i)) % 10
            tmp[idx].append(j)
        start = 0
        for v in tmp:
            arr[start : start + len(v)] = v
            start += len(v)
        tmp = [[] for _ in range(10)]

时间空间复杂度

排序算法平均时间复杂度最好情况最坏情况空间复杂度原地排序稳定性
冒泡排序O(n²)O(n)O(n²)O(1)True稳定
选择排序O(n²)O(n²)O(n²)O(1)True不稳定
插入排序O(n²)O(n)O(n²)O(1)True稳定
希尔排序O(nlogn)O(nlog²n)O(nlog²n)O(1)True不稳定
归并排序O(nlogn)O(nlogn)O(nlogn)O(n)False稳定
快速排序O(nlogn)O(nlogn)O(n²)O(logn)True不稳定
堆排序O(nlogn)O(nlogn)O(nlogn)O(1)True不稳定
计数排序O(n+k)O(n+k)O(n+k)O(k)False稳定
桶排序O(n+k)O(n+k)O(n²)O(n+k)False稳定
基数排序O(n*k)O(n*k)O(n*k)O(n+k)False稳定

还有另一些特定场景的排序:睡眠排序、面条排序、猴子排序等等。

参考文档:

https://www.cnblogs.com/itsharehome/p/11058010.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值