Python实现5大排序算法

本文介绍5种常见的排序算法和基于Python实现:

  1. 冒泡排序(Bubble Sort):通过不断交换相邻元素,将较大的元素逐渐“冒泡”到数组的尾部,较小的元素逐渐沉到数组的头部。
  2. 选择排序(Selection Sort):每次从未排序的部分中选择最小(或最大)的元素,然后放到已排序部分的末尾(或开头)。
  3. 插入排序(Insertion Sort):将数组分为已排序和未排序两部分,逐个将未排序元素插入到已排序部分的适当位置,使其保持有序。
  4. 快速排序(Quick Sort):通过递归地选择一个基准元素,并将数组划分为小于基准和大于基准的两部分,然后对两部分继续进行快速排序。
  5. 归并排序(Merge Sort):将数组拆分成两个子数组,对每个子数组进行排序,然后再将两个有序子数组合并成一个有序数组。

不同的排序算法在时间复杂度、空间复杂度以及稳定性等方面有所不同,选择适合具体情况的排序算法可以提高排序效率。

文末粉丝福利,不容错过

排序算法

冒泡排序是一种简单的排序算法,它的思想是重复地走访过要排序的元素列,依次比较相邻的两个元素,如果它们的顺序错误就交换它们,直到没有任何再需要交换的元素,排序完成。以下是Python实现冒泡排序的代码:

def bubble_sort(arr):
    n = len(arr)
    for i in range(n - 1):
        # 标志位,用于优化:若某次循环中没有交换元素,说明数组已经有序,可以提前结束排序
        swapped = False
        for j in range(n - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
                swapped = True
        if not swapped:
            break

# 使用示例
arr = [64, 34, 25, 12, 22, 11, 90]
bubble_sort(arr)
print(arr)  # 输出:[11, 12, 22, 25, 34, 64, 90]

在冒泡排序中,外层循环控制需要比较的次数,内层循环实际进行相邻元素的比较和交换。通过标志位swapped的引入,可以优化冒泡排序,当某次循环没有发生交换时,说明数组已经有序,可以提前结束排序。这样在数组近乎有序的情况下,冒泡排序的性能会有所提升。

优化后的版本:

def bubble_sort(arr):
    n = len(arr)
    for i in range(n - 1):
        swapped = False
        # 记录当前轮循环最后一次交换的位置,初始值为未排序部分的末尾
        last_swap_index = n - 1

        for j in range(n - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
                swapped = True
                last_swap_index = j  # 更新最后一次交换的位置

        if not swapped:
            break
            

        # 更新下一轮未排序部分的边界
        n = last_swap_index + 1

# 使用示例
arr = [64, 34, 25, 12, 22, 11, 90]
bubble_sort(arr)
print(arr)  # 输出:[11, 12, 22, 25, 34, 64, 90]

选择排序

选择排序(Selection Sort)是一种简单直观的排序算法,其思想是在未排序部分找到最小(或最大)元素,然后与未排序部分的第一个元素交换位置。重复这个过程直到所有元素都有序。以下是Python实现选择排序的代码:

def selection_sort(arr):
    n = len(arr)
    for i in range(n - 1):
        # 假设当前未排序部分的第一个元素是最小的
        min_idx = i

        # 在未排序部分中找到最小元素的索引
        for j in range(i + 1, n):
            if arr[j] < arr[min_idx]:
                min_idx = j

        # 将找到的最小元素与未排序部分的第一个元素交换位置
        arr[i], arr[min_idx] = arr[min_idx], arr[i]

# 使用示例
arr = [64, 34, 25, 12, 22, 11, 90]
selection_sort(arr)
print(arr)  # 输出:[11, 12, 22, 25, 34, 64, 90]

在选择排序中,外层循环控制需要排序的次数,内层循环在未排序部分中找到最小元素的索引。然后将找到的最小元素与未排序部分的第一个元素交换位置。这样每一轮循环会将未排序部分的最小元素放到已排序部分的末尾,从而实现排序。选择排序的时间复杂度是O(n^2),它是一个不稳定的排序算法。

def selection_sort(arr):
    n = len(arr)
    for i in range(n - 1):
        min_idx = i

        for j in range(i + 1, n):
            if arr[j] < arr[min_idx]:
                min_idx = j

        # 如果最小元素的索引不是当前的第一个元素,才进行交换
        if min_idx != i:
            arr[i], arr[min_idx] = arr[min_idx], arr[i]

# 使用示例
arr = [64, 34, 25, 12, 22, 11, 90]
selection_sort(arr)
print(arr)  # 输出:[11, 12, 22, 25, 34, 64, 90]

通过增加一个条件判断,只有当最小元素的索引不等于当前的第一个元素的索引时,才进行交换操作。这样就可以减少不必要的交换,进而优化选择排序的性能。这个优化对于已经近乎有序的数组尤为有效,因为这些情况下交换次数较少。尽管选择排序的时间复杂度仍然是O(n^2),但这样的优化可以提高它的效率。

插入排序

插入排序(Insertion Sort)是一种简单的排序算法,其基本思想是将数组分为已排序和未排序两个部分,逐个将未排序元素插入到已排序部分的适当位置,使其保持有序。以下是Python实现插入排序的代码:

def insertion_sort(arr):
    n = len(arr)
    for i in range(1, n):
        key = arr[i]  # 当前要插入的元素
        j = i - 1  # 已排序部分的最后一个元素的索引

        # 逐个将已排序部分中比key大的元素后移,为key找到合适的插入位置
        while j >= 0 and key < arr[j]:
            arr[j + 1] = arr[j]
            j -= 1

        # 插入key到合适的位置
        arr[j + 1] = key

# 使用示例
arr = [64, 34, 25, 12, 22, 11, 90]
insertion_sort(arr)
print(arr)  # 输出:[11, 12, 22, 25, 34, 64, 90]

在插入排序中,外层循环控制需要插入的次数,从第2个元素开始(索引为1),依次向已排序部分插入未排序部分的元素。内层循环用于将已排序部分中比当前元素key大的元素后移,为key找到合适的插入位置。最后,将key插入到合适的位置,完成一次插入操作。

插入排序的时间复杂度是O(n^2),它是一个稳定的排序算法。对于小规模的数组或近乎有序的数组,插入排序可能会比其他更复杂的排序算法表现更好。

优化后的版本:

def insertion_sort(arr):
    n = len(arr)
    for i in range(1, n):
        key = arr[i]
        left, right = 0, i - 1

        # 使用二分查找找到key应该插入的位置
        while left <= right:
            mid = (left + right) // 2
            if arr[mid] > key:
                right = mid - 1
            else:
                left = mid + 1

        # 将已排序部分中大于key的元素都后移一位
        for j in range(i, left, -1):
            arr[j] = arr[j - 1]

        arr[left] = key

# 使用示例
arr = [64, 34, 25, 12, 22, 11, 90]
insertion_sort(arr)
print(arr)  # 输出:[11, 12, 22, 25, 34, 64, 90]

快速排序

快速排序(Quick Sort)是一种高效的排序算法,它使用分治法来对数组进行排序。快速排序的基本思想是选择一个基准元素(pivot),然后将数组中小于等于基准的元素放在左边,大于基准的元素放在右边,然后分别对左右两部分递归地进行快速排序,直到整个数组有序为止。以下是Python实现快速排序的代码:

def quick_sort(arr):
    if len(arr) <= 1:
        return arr

    pivot = arr[len(arr) // 2]  # 选择中间的元素作为基准
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]

    return quick_sort(left) + middle + quick_sort(right)

# 使用示例
arr = [64, 34, 25, 12, 22, 11, 90]
sorted_arr = quick_sort(arr)
print(sorted_arr)  # 输出:[11, 12, 22, 25, 34, 64, 90]

在优化快速排序的代码中,主要关注减少递归调用的次数和减少额外空间的使用。以下是针对这两方面的优化方法:

  1. 优化递归调用次数:对于小规模的子数组,可以切换到其他排序算法,例如插入排序。这是因为在小规模数据下,插入排序的常数项较小,比快速排序的递归开销更小。
  2. 减少额外空间的使用:原始的快速排序需要额外的数组空间用于存放左右子数组,但我们可以通过就地分区的方式来减少空间使用。

下面是优化后的快速排序代码:

def insertion_sort(arr, low, high):
    for i in range(low + 1, high + 1):
        key = arr[i]
        j = i - 1
        while j >= low and key < arr[j]:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = key

def partition(arr, low, high):
    pivot = arr[high]
    i = low - 1
    for j in range(low, high):
        if arr[j] <= pivot:
            i += 1
            arr[i], arr[j] = arr[j], arr[i]
    arr[i + 1], arr[high] = arr[high], arr[i + 1]
    return i + 1

def quick_sort(arr, low, high):
    if low < high:
        # 对于小规模的子数组,切换到插入排序
        if high - low + 1 <= 10:
            insertion_sort(arr, low, high)
        else:
            pivot_index = partition(arr, low, high)
            quick_sort(arr, low, pivot_index - 1)
            quick_sort(arr, pivot_index + 1, high)

# 使用示例
arr = [64, 34, 25, 12, 22, 11, 90]
quick_sort(arr, 0, len(arr) - 1)
print(arr)  # 输出:[11, 12, 22, 25, 34, 64, 90]

在优化后的代码中,我们引入了insertion_sort函数用于对小规模子数组进行插入排序。当子数组大小不超过10个元素时,切换到插入排序。同时,在quick_sort函数中采用就地分区的方法,减少了额外的空间使用。

这些优化方法可以提高快速排序在小规模数据和近乎有序数组的性能。但需要注意的是,优化的效果也依赖于具体的数据情况。

归并排序

归并排序(Merge Sort)是一种高效稳定的排序算法,它使用分治法将数组分为两个子数组,递归地对子数组进行排序,然后将排好序的子数组合并成一个有序数组。以下是Python实现归并排序的代码:

def merge_sort(arr):
    if len(arr) <= 1:
        return arr

    # 将数组一分为二
    mid = len(arr) // 2
    left = arr[:mid]
    right = arr[mid:]

    # 递归对左右两部分进行归并排序
    left = merge_sort(left)
    right = merge_sort(right)

    # 合并已排序的左右两部分
    return merge(left, right)

def merge(left, right):
    merged = []
    left_idx, right_idx = 0, 0

    while left_idx < len(left) and right_idx < len(right):
        if left[left_idx] < right[right_idx]:
            merged.append(left[left_idx])
            left_idx += 1
        else:
            merged.append(right[right_idx])
            right_idx += 1

    # 将剩余的元素加入合并后的数组
    merged.extend(left[left_idx:])
    merged.extend(right[right_idx:])

    return merged

# 使用示例
arr = [64, 34, 25, 12, 22, 11, 90]
sorted_arr = merge_sort(arr)
print(sorted_arr)  # 输出:[11, 12, 22, 25, 34, 64, 90]

关于Python学习指南

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后给大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

包括:Python激活码+安装包、Python web开发,Python爬虫,Python数据分析,人工智能、自动化办公等学习教程。带你从零基础系统性的学好Python!

👉Python所有方向的学习路线👈

Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。(全套教程文末领取)

在这里插入图片描述

👉Python学习视频600合集👈

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

在这里插入图片描述

温馨提示:篇幅有限,已打包文件夹,获取方式在:文末

👉Python70个实战练手案例&源码👈

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

在这里插入图片描述

👉Python大厂面试资料👈

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

在这里插入图片描述

在这里插入图片描述

👉Python副业兼职路线&方法👈

学好 Python 不论是就业还是做副业赚钱都不错,但要学会兼职接单还是要有一个学习规划。

在这里插入图片描述

👉 这份完整版的Python全套学习资料已经上传,朋友们如果需要可以扫描下方CSDN官方认证二维码或者点击链接免费领取保证100%免费

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值