当前位置: 首页 > article >正文

Python排序算法详解

一、简单排序算法

1. 冒泡排序(Bubble Sort)
  • 算法思想:通过相邻元素的比较和交换,逐步将最大元素“冒泡”到数组末尾。

  • 时间复杂度

    • 平均:O(n²)

    • 最优(已排序):O(n)

  • 稳定性:稳定

  • 代码实现

    # 定义一个名为 bubble_sort 的函数,该函数接受一个列表 arr 作为参数
    # 此函数的目的是使用冒泡排序算法对传入的列表进行升序排序
    def bubble_sort(arr):
        # 获取列表 arr 的长度,存储在变量 n 中
        # 列表长度决定了后续排序操作需要比较和交换元素的范围
        n = len(arr)
    
        # 外层循环控制排序的轮数,总共需要进行 n 轮
        # 每一轮都会将当前未排序部分中的最大元素“冒泡”到正确的位置
        for i in range(n):
            # 初始化一个布尔变量 swapped 为 False
            # 用于标记在当前这一轮排序中是否发生了元素交换
            # 如果一轮排序中没有发生交换,说明列表已经有序,可以提前结束排序
            swapped = False  
    
            # 内层循环用于比较相邻元素并在必要时进行交换
            # 由于每一轮排序后,最大的元素已经被放置在正确的位置,所以每一轮需要比较的元素范围会逐渐减小
            # n - i - 1 表示当前未排序部分的最后一个元素的索引
            for j in range(0, n - i - 1):
                # 比较相邻的两个元素 arr[j] 和 arr[j + 1]
                # 如果前一个元素大于后一个元素,说明它们的顺序不符合升序要求
                if arr[j] > arr[j + 1]:
                    # 交换 arr[j] 和 arr[j + 1] 的位置
                    # 这样可以将较大的元素往后移动,较小的元素往前移动
                    arr[j], arr[j + 1] = arr[j + 1], arr[j]
                    # 一旦发生了元素交换,将 swapped 标记为 True
                    swapped = True
    
            # 检查当前轮次是否发生了元素交换
            # 如果 swapped 仍然为 False,说明在这一轮中没有进行任何交换,即列表已经有序
            if not swapped:
                # 此时可以提前结束排序过程,避免不必要的比较
                break
    
        # 排序完成后,返回排序好的列表
        return arr
  • 适用场景:小规模数据或基本有序的数组。


2. 选择排序(Selection Sort)
  • 算法思想:每次从未排序部分选择最小元素,放到已排序部分的末尾。即选择排序的工作原理是每一次从需要排序的数据元素中选出最小的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排列完毕。

  • 时间复杂度:O(n²)(无论数据是否有序)

  • 稳定性:不稳定(可能破坏原有相等元素的相对顺序)

  • 代码实现

    def selection_sort(arr):
        n = len(arr)
        for i in range(n):
            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]
        return arr
  • 适用场景:简单且不要求稳定性的场景。


3. 插入排序(Insertion Sort)
  • 算法思想:将未排序元素逐个插入到已排序部分的正确位置。

  • 时间复杂度

    • 平均:O(n²)

    • 最优(已排序):O(n)

  • 稳定性:稳定

  • 代码实现

    def insertion_sort(arr):
        for i in range(1, len(arr)):
            key = arr[i]
            j = i-1
            while j >=0 and key < arr[j]:
                arr[j+1] = arr[j]
                j -= 1
            arr[j+1] = key
        return arr
  • 适用场景:小规模数据或基本有序的数组。


二、分治排序算法

1. 快速排序(Quick Sort)
  • 算法思想:分治法 + 基准值分区。选择一个基准值,小于基准值的放左边,大于基准值的放右边,每次比较之后,当下指针向中间移一位,若改变了元素位置则左右交替进行,为改变则继续比较此指针。

  • 时间复杂度

    • 平均:O(n log n)

    • 最坏(有序数组):O(n²)

  • 稳定性:不稳定

  • 代码实现

    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)
  • 优化技巧

    • 随机化基准值:pivot = random.choice(arr)

    • 三向切分(处理大量重复元素)

  • 适用场景:大规模随机数据,通用排序需求。


2. 归并排序(Merge Sort)
  • 算法思想:分治法 + 合并有序子序列。

  • 时间复杂度:O(n log n)(稳定)

  • 稳定性:稳定

  • 代码实现

    def merge_sort(arr):
        if len(arr) <= 1:
            return arr
        mid = len(arr) // 2
        left = merge_sort(arr[:mid])
        right = merge_sort(arr[mid:])
        return merge(left, right)
    
    def merge(left, right):
        result = []
        i = j = 0
        while i < len(left) and j < len(right):
            if left[i] <= right[j]:
                result.append(left[i])
                i += 1
            else:
                result.append(right[j])
                j += 1
        result += left[i:]
        result += right[j:]
        return result
  • 适用场景:链表排序、需要稳定性的场景(如蓝桥杯“逆序对”问题)。


三、线性时间复杂度排序

1. 计数排序(Counting Sort)
  • 算法思想:统计每个元素的出现次数,按顺序输出。

  • 时间复杂度:O(n + k)(k为数据范围)

  • 稳定性:稳定

  • 代码实现

    def counting_sort(arr, max_val):
        count = [0] * (max_val + 1)
        for num in arr:
            count[num] += 1
        sorted_arr = []
        for i in range(max_val + 1):
            sorted_arr.extend([i] * count[i])
        return sorted_arr
  • 适用场景:数据范围较小的整数排序(如成绩、年龄)。


2. 桶排序(Bucket Sort)
  • 算法思想:将数据分到多个桶中,对每个桶单独排序后合并。

  • 时间复杂度:O(n + k)(k为桶数量)

  • 稳定性:取决于桶内排序算法

  • 代码实现

    def bucket_sort(arr, bucket_size=5):
        min_val, max_val = min(arr), max(arr)
        bucket_count = (max_val - min_val) // bucket_size + 1
        buckets = [[] for _ in range(bucket_count)]
        for num in arr:
            idx = (num - min_val) // bucket_size
            buckets[idx].append(num)
        sorted_arr = []
        for bucket in buckets:
            sorted_arr.extend(sorted(bucket))  # 桶内使用其他排序算法
        return sorted_arr
  • 适用场景:数据均匀分布的场景。


四、其他排序算法

1. 堆排序(Heap Sort)
  • 算法思想:构建最大堆,逐个取出堆顶元素。

  • 时间复杂度:O(n log n)

  • 稳定性:不稳定

  • 代码实现

    def heap_sort(arr):
        def heapify(arr, n, i):
            largest = i
            left = 2*i + 1
            right = 2*i + 2
            if left < n and arr[left] > arr[largest]:
                largest = left
            if right < n and arr[right] > arr[largest]:
                largest = right
            if largest != i:
                arr[i], arr[largest] = arr[largest], arr[i]
                heapify(arr, n, largest)
        
        n = len(arr)
        # 建堆
        for i in range(n//2-1, -1, -1):
            heapify(arr, n, i)
        # 逐个提取元素
        for i in range(n-1, 0, -1):
            arr[i], arr[0] = arr[0], arr[i]
            heapify(arr, i, 0)
        return arr
  • 适用场景:Top K问题、需要原地排序的场景。

五、排序算法总结与蓝桥杯应用

算法平均时间复杂度稳定性适用场景蓝桥杯典型题目
快速排序O(n log n)不稳定大规模随机数据数列排序、分巧克力
归并排序O(n log n)稳定需要稳定性的场景(如逆序对)逆序对统计
堆排序O(n log n)不稳定Top K问题、内存受限前K高频元素
计数排序O(n + k)稳定小范围整数成绩统计(0~100分)
插入排序O(n²)稳定小规模或基本有序数据简单排序题

http://www.kler.cn/a/550847.html

相关文章:

  • 坐井说天阔---DeepSeek-R1
  • 设计模式2:单例模式
  • Docker 容器日志与监控
  • 【对比】Pandas 和 Polars 的区别
  • Unity截取RenderTexture某帧画面显示在Image上
  • Leetcode 算法题 88. 合并两个有序数组
  • 802.3 两种格式
  • Redis 10章——集群(cluster)
  • 服务器A到服务器B免密登录
  • 【拒绝算法PUA】LeetCode 1287. 有序数组中出现次数超过25%的元素
  • maven使用默认settings.xml配置时,Idea基于pom.xml更新依赖时报错,有些组件下载时连接超时
  • 解锁JavaScript新姿势:Set数据结构深度解析
  • Unity Shader示例 6: 卡渲基础 - 描边 + 着色
  • 【学术投稿-第四届智能电网和绿色能源国际学术会议(ICSGGE 2025)】CSS基本选择器详解:掌握基础,轻松布局网页
  • 深入剖析 Python 爬虫:淘宝商品详情数据抓取
  • 什么是RDD以及它在Spark中的作用
  • 地基Spring中bean生命周期和设计模式
  • 为AI聊天工具添加一个知识系统 之108 详细设计之49 相提并论的三者、三位一体Triad和圣灵倒三角
  • Java爬虫获取1688商品搜索API接口的实现指南
  • 案例-05.部门管理-新增