Python排序算法详解

一、简单排序算法

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

  • 时间复杂度

    • 平均:O(n²)

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

  • 稳定性:稳定

  • 代码实现

    python 复制代码
    # 定义一个名为 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²)(无论数据是否有序)

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

  • 代码实现

    python 复制代码
    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)

  • 稳定性:稳定

  • 代码实现

    python 复制代码
    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²)

  • 稳定性:不稳定

  • 代码实现

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

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

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

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


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

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

  • 稳定性:稳定

  • 代码实现

    python 复制代码
    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为数据范围)

  • 稳定性:稳定

  • 代码实现

    python 复制代码
    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为桶数量)

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

  • 代码实现

    python 复制代码
    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)

  • 稳定性:不稳定

  • 代码实现

    python 复制代码
    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²) 稳定 小规模或基本有序数据 简单排序题
相关推荐
鸡鸭扣1 小时前
Docker:3、在VSCode上安装并运行python程序或JavaScript程序
运维·vscode·python·docker·容器·js
paterWang1 小时前
基于 Python 和 OpenCV 的酒店客房入侵检测系统设计与实现
开发语言·python·opencv
东方佑1 小时前
使用Python和OpenCV实现图像像素压缩与解压
开发语言·python·opencv
我真不会起名字啊2 小时前
“深入浅出”系列之杂谈篇:(3)Qt5和Qt6该学哪个?
开发语言·qt
神秘_博士2 小时前
自制AirTag,支持安卓/鸿蒙/PC/Home Assistant,无需拥有iPhone
arm开发·python·物联网·flutter·docker·gitee
laimaxgg2 小时前
Qt常用控件之单选按钮QRadioButton
开发语言·c++·qt·ui·qt5
水瓶丫头站住2 小时前
Qt的QStackedWidget样式设置
开发语言·qt
Moutai码农3 小时前
机器学习-生命周期
人工智能·python·机器学习·数据挖掘
尼尔森系4 小时前
排序与算法:希尔排序
c语言·算法·排序算法
小钊(求职中)4 小时前
Java开发实习面试笔试题(含答案)
java·开发语言·spring boot·spring·面试·tomcat·maven