【算法】十大排序算法python实现

目录

在这里插入图片描述


冒泡排序

在这里插入图片描述

基本实现

依次比较相邻两个元素的大小

def bubbleSort(l):
    n = len(l)-1
    for i in range(n):
        for j in range(0, n-i):
            if l[j] > l[j+1]:
                l[j], l[j+1] = l[j+1], l[j]
    return l
优化

原始的冒泡排序算法有一个问题,比如原始的数列是[2, 1, 3, 4, 5, 6],即使在遍历一次之后就已经排序完成,程序仍会继续执行,所以我们加入一个flag参数来判断是否是已经排序完成。

def bubbleSort(l):
    n = len(l)-1
    for i in range(n):
        flag = False
        for j in range(0, n-i):
            if l[j] > l[j+1]:
                l[j], l[j+1] = l[j+1], l[j]
                flag = True
        if not flag:
            return l
    return l
选择排序

在这里插入图片描述

基本实现

将队列分为两部分,前一部分是已经排序好的部分,每一次从未排序好的部分取出最小值插入已排序序列的末尾

def selectionSort(l):
    n = len(l)
    for i in range(n):
        min_index = i
        for j in range(i+1, n):
            if l[j] < l[min_index]:
                min_index = j
        if i != min_index:
            l[i], l[min_index] = l[min_index], l[i]
    return l
优化

每一次遍历确定一个最小值和一个最大值,进行双向选择排序
另外加入一个小的优化,当某一轮选出的最大最小值相等时,排序完成

def selectionSort(l):
    n = len(l)
    for i in range(n//2):
        min_index = i
        max_index = -i-1
        for j in range(i+1, n-1-i):
            if l[j] < l[min_index]:
                min_index = j
            if l[j] > l[max_index]:
                max_index = j
        # 判断这一轮选出的最大最小值是否相等
        if l[min_index] == l[max_index]:
            break
        if i != min_index:
            l[i], l[min_index] = l[min_index], l[i]
        if -i-1 != max_index:
            l[-i-1], l[max_index] = l[max_index], l[-i-1]
        print(l)
    return l
插入排序

在这里插入图片描述

基本实现

将数列分为两部分,前一部分为一排序数列,后一部分为未排序数列,每次从未排列数列中取出第一个数按顺序插入已排序数列

def insertSort(l):
    n = len(l)
    for i in range(n):
        j = i-1
        num = l[i]
        while j>=0 and l[j]>num:
            l[j+1] = l[j]
            j -= 1
        l[j+1] = num
    return l
优化

在执行插入操作时,搜索部分使用二分法查找

def insertSort(l):
    n = len(l)
    for i in range(n):
        num = l[i]
        right = i-1
        left = 0
        while left<=right:
            mid = (left+right)//2
            if l[mid] == num:
                left = mid
                break
            elif l[mid] > num:
                right = mid-1
            else:
                left = mid+1
        for s in range(i-1, left-1, -1):
            l[s+1] = l[s]
        l[left] = num
        print(l)
    return l
希尔排序

在这里插入图片描述

基本实现
def shellSort(l):
    n = len(l)
    gap = n//2
    while gap > 0:
        for i in range(gap, n):
            while i>=gap and l[i] < l[i-gap]:
                l[i], l[i-gap] = l[i-gap], l[i]
                i -= gap
        gap = gap//2
    return l
归并排序

在这里插入图片描述

基本实现
def merge(s1, s2, s):
    i = j = 0 
    while i+j<len(s):
        if j==len(s2) or (i<len(s1) and s1[i]<s2[j]):
            s[i+j] = s1[i]
            i += 1
        else:
            s[i+j] = s2[j]
            j += 1

def mergeSort(s):
    n = len(s) 
    if n<=1:
        return
    mid = n//2
    s1 = s[0:mid]
    s2 = s[mid:n]
    mergeSort(s1)
    mergeSort(s2)
    merge(s1, s2, s)
    return s
快速排序

在这里插入图片描述

基本实现
def quickSort(s):
    if len(s)<=1:
        return
    # select a random number as pivot
    p = s[0]
    left = []
    right = []
    mid = []
    while s:
        if s[-1] == p:
            mid.append(s.pop())
        elif s[-1] <= p:
            left.append(s.pop())
        else:
            right.append(s.pop())
    quickSort(left)
    quickSort(right)
    s.extend(left)
    s.extend(mid)
    s.extend(right)
    return s
堆排序

在这里插入图片描述

基本实现

通过将列表构建为堆,每次选出最大的值

def max_heapify(heap, heapsize, root):
    left = 2*root + 1
    right = left + 1
    largest = root
    if left<heapsize and heap[left]>heap[largest]:
        largest = left
    if right<heapsize and heap[right]>heap[largest]:
        largest = right
    if largest != root:
        heap[root], heap[largest] = heap[largest], heap[root]
        max_heapify(heap, heapsize, largest)
def build_max_heap(heap):
    heapsize = len(heap)
    for i in range((heapsize-2)//2, -1, -1):
        max_heapify(heap, heapsize, i)
def heapSort(s):
    build_max_heap(s)
    for i in range(len(s)-1, -1, -1):
        s[0], s[i] = s[i], s[0]
        max_heapify(s, i, 0)
    return s

max_heapify(heap, heapsize, root)函数用来调节父节点与字节点的位置并递归来始终保持大根堆结构
build_max_heap(heap) 函数用来构建大根堆

计数排序

在这里插入图片描述

基本实现

选出数列中最大值和最小值,创建一个长度为 最大值-最小值+1 的数列用来计数,遍历原队列,将各个数据的出现次数存储在计数数列中

def countSort(s):
    max_num = max(s)
    min_num = min(s)
    count = [0 for i in range(max_num-min_num+1)]
    for i in s:
        count[i-min_num] += 1
    s.clear()
    for index, num in enumerate(count):
        for i in range(num):
            s.append(min_num+index)
    return s
桶排序

在这里插入图片描述

基本实现

桶排序的基本思路为,先设置若干个空桶,并给每一个桶设定所存储的范围,依次遍历数列中的每一个元素,将每个元素插入对应范围的桶内,插入时使用插入排序,确保每个桶内元素排列是有序的,最后依次将各个不为空的桶组合就是排列好的有序数列

关于桶个数的选择并没有明确答案,我在网上看到的一种说法是在占用空间允许的情况下,桶的个数越多越好,具体如何有待考证

def insert(arr, num):
    arr.append(num)
    i = len(arr)-2
    while i>=0:
        if num<arr[i]:
            arr[i+1] = arr[i]
            i -= 1
        else:
            break
    arr[i+1] = num
    return arr
def bucketSort(s):
    # choose the number of buckets
    buckets = 5
    arr = [[] for i in range(buckets)]
    max_num = max(s)
    min_num = min(s)
    size = (max_num-min_num+1)//buckets + 1
    for i in s:
        index = (i-min_num)//size
        insert(arr[index], i)
    s.clear()
    print(arr)
    for j in arr:
        if len(j) != 0:
            s.extend(j)
    return s
基数排序

在这里插入图片描述

基本实现

基数排序的思路为,从个位开始依次对各个位数上的数字进行排序

def radixSort(s):
    i = 0
    while i<len(str(max(s))):
        buckets = [[] for s in range(10)]
        for num in s:
            last_num = (num//(10**i)) % 10
            buckets[last_num].append(num)
        s.clear()
        for j in buckets:
            s.extend(j)
        i += 1
    return s

在我写完之后发现一个很明显的问题,以上算法无法处理有负数的情况,我第一反应是将正负数分开排序,但是我在网上找到了一个很妙的解决方案,将所有的元素统一加上一个数字,都变成正数。

def radixSort(s):
    add_num = abs(min(s))
    for i in range(len(s)):
        s[i] += add_num
        
    i = 0
    while i<len(str(max(s))):
        buckets = [[] for s in range(10)]
        for num in s:
            last_num = (num//(10**i)) % 10
            buckets[last_num].append(num)
        s.clear()
        for j in buckets:
            s.extend(j)
        i += 1
        
    for i in range(len(s)):
        s[i] -= add_num
    return s
相关资料

以上所使用的图片均来自《5分钟学算法》的文章:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值