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²) 稳定 小规模或基本有序数据 简单排序题
相关推荐
小白教程3 分钟前
Python爬取视频的架构方案,Python视频爬取入门教程
python·架构·音视频·python爬虫·python视频爬虫·python爬取视频教程
昂子的博客11 分钟前
热门面试题第15天|最大二叉树 合并二叉树 验证二叉搜索树 二叉搜索树中的搜索
java·数据结构·算法
东方窅瞳15 分钟前
Bash语言的哈希表
开发语言·后端·golang
ん贤32 分钟前
蓝桥杯考前复盘
c语言·c++·算法·职场和发展·蓝桥杯
HarrisHaword41 分钟前
JAVA 导出 word
java·开发语言·word
PingdiGuo_guo1 小时前
C++指针(四)万字图文详解!
开发语言·c++
s9123601011 小时前
Rust Command无法执行*拓展解决办法
开发语言·后端·rust
仰望星空的小随1 小时前
django相关面试题
python·django·sqlite
pk_xz1234561 小时前
MATLAB编写的机械臂控制仿真程序,它主要实现了对一个二连杆机械臂的运动控制仿真,比较了PID控制和非线性模型预测控制两种方法在机械臂轨迹跟踪任务中的性能
开发语言·matlab
想成为配环境大佬1 小时前
P8697 [蓝桥杯 2019 国 C] 最长子序列
算法·蓝桥杯·双指针