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

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²)稳定小规模或基本有序数据简单排序题

相关文章:

  • 一键高清修复、智能剪辑,媒体处理还能多智能?
  • 什么是网关?网关有什么作用?API网关的主要功能,SpringCloud可以选择有哪些API网关?什么是限流算法?网关如何实现限流?一篇文章读懂网关的前世今生
  • 国产网络变压器有哪些品牌比较好
  • Record-Mode 备案免关站插件,让 WordPress 备案不影响 SEO 和收录
  • 网络安全-防御 第一次作业(由于防火墙只成功启动了一次未补截图)
  • redis之lua实现原理
  • 07:串口通信(二):收发数据包
  • Docker Desktop之Nginx
  • HTTP的状态码
  • 海思3559a_使用2.0.4.0版SDK编译固件下载后i2c_write和i2c_read不支持怎么办
  • OpenCV机器学习(4)k-近邻算法(k-Nearest Neighbors, KNN)cv::ml::KNearest类
  • 蓝桥杯(B组)-每日一题(求最大公约数最小公倍数)
  • MongoDB 7 分片副本集升级方案详解(下)
  • 用Echarts的柱状图实现圆柱体效果
  • linux c 读写锁pthread_rwlock
  • 3D打印技术:如何让古老文物重获新生?
  • MYSQL直接在SQL提取json字符串中的内容-----将13位时间戳转换成标准的日期格式【记录SQL常用函数】
  • 【如何掌握CSP-J 信奥赛中的模拟算法】
  • Python深度学习代做目标检测NLP计算机视觉强化学习
  • 【Linux系统】—— 简易进度条的实现
  • 山西持续高温:阳城地表温度72.9℃破纪录,明日局部地区仍将超40℃
  • 国家发改委:安全是低空经济发展的首要前提,稳妥推进低空旅游、航空运动等发展
  • 益阳通报“河水颜色异常有死鱼”:未发现排污,原因待鉴定
  • 不赚“快钱”的佳沛:蒋时杰解密新西兰国果如何在中国“慢养”出43亿生意
  • 大学2025丨专访西湖大学副校长邓力:如何才能培养“不惧未知”的创新者
  • 回家了!子弹库帛书二、三卷将于7月首次面向公众展出