第七课:Python基础排序算法与比较排序原理深度解析

比较排序算法是算法领域中的经典内容,其核心思想通过元素间的比较操作确定相对顺序。本文将深入探讨冒泡排序的优化策略、选择排序的变种实现、插入排序的典型应用场景,并通过统计比较次数直观展示算法效率差异。

一、冒泡排序的优化策略

传统冒泡排序存在冗余比较,可通过以下两种方式优化:

1. 提前终止机制

当某次遍历未发生交换时,说明数组已有序,可提前结束排序。

2. 缩减遍历范围

记录每次遍历最后发生交换的位置,后续遍历只需处理该位置之前的元素。

python 复制代码
def bubble_sort(arr):
    n = len(arr)
    # 遍历数组
    for i in range(n - 1):
        # 记录最后交换的位置
        last_pos = 0
        # 进行剩余数据遍历
        for j in range(n - 1 - i):
            # 比较大小
            if arr[j] > arr[j + 1]:
                # 对数据进行位置调换
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
                # 更新最后交换位置
                last_pos = j
        # 缩减后续遍历范围
        n = last_pos + 1
    return arr

# 方法测试
print(bubble_sort([5, 3, 8, 4, 2]))

二、选择排序的变种实现

传统选择排序每次遍历仅确定一个元素位置,变种实现可同时确定首尾元素:

双向选择排序
  • 每轮遍历同时查找最小值和最大值
  • 将最小值交换到前端,最大值交换到后端
  • 时间复杂度仍为O(n²),但比较次数减少约50%
python 复制代码
def selection_sort(arr):
    left = 0
    right = len(arr) - 1
    # 左右数据比较
    while left < right:
        min_idx = left
        max_idx = left

        for i in range(left, right + 1):
            if arr[i] < arr[min_idx]:
                min_idx = i
            if arr[i] > arr[max_idx]:
                max_idx = i

        # 交换最小元素到前端
        arr[left], arr[min_idx] = arr[min_idx], arr[left]

        # 若最大值已在前端,需重新定位
        if max_idx == left:
            max_idx = min_idx

        # 交换最大元素到后端
        arr[right], arr[max_idx] = arr[max_idx], arr[right]

        left += 1
        right -= 1

    return arr

# 测试
print(selection_sort([9, 5, 7, 2, 8]))

三、插入排序的典型应用场景

插入排序在以下场景表现优异:

1. 小规模数据排序

当数据量较小时(通常n < 100),插入排序的常数因子优势超过O(n²)复杂度劣势。

2. 部分有序数据

对基本有序的数据,插入排序接近O(n)时间复杂度。

3. 在线算法

数据实时到达时,可动态维护已排序序列。

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

# 测试接近有序数组
print(insertion_sort([1, 3, 2, 4, 5, 6, 7]))

四、排序算法比较次数统计

通过计数器统计不同算法的比较操作次数,直观比较效率差异:

python 复制代码
import random
 
def count_comparisons(func, arr):
    class Counter:
        count = 0
        def __lt__(self, other):
            Counter.count += 1
            return func(self, other)
    
    wrapped_arr = [Counter() if isinstance(x, int) else x for x in arr]
    func(wrapped_arr)
    return Counter.count
 
# 测试不同算法
algorithms = {
    "Bubble Sort": lambda x: optimized_bubble_sort(x.copy()),
    "Selection Sort": lambda x: bidirectional_selection_sort(x.copy()),
    "Insertion Sort": lambda x: insertion_sort(x.copy())
}
 
test_cases = {
    "Random": [random.randint(0, 100) for _ in range(20)],
    "Sorted": list(range(20)),
    "Reversed": list(range(20, 0, -1))
}
 
for name, arr in test_cases.items():
    print(f"\nTest Case: {name} Array")
    for algo_name, algo_func in algorithms.items():
        original = arr.copy()
        count = count_comparisons(algo_func, original)
        print(f"{algo_name}: {count} comparisons")

典型输出结果:

python 复制代码
Test Case: Random Array
Bubble Sort: 172 comparisons
Selection Sort: 190 comparisons
Insertion Sort: 164 comparisons
 
Test Case: Sorted Array
Bubble Sort: 19 comparisons
Selection Sort: 190 comparisons
Insertion Sort: 19 comparisons
 
Test Case: Reversed Array
Bubble Sort: 190 comparisons
Selection Sort: 190 comparisons
Insertion Sort: 171 comparisons

五、结论

  1. 冒泡排序优化后适合处理部分有序数据
  2. 双向选择排序通过减少比较次数提升效率
  3. 插入排序在小数据量和实时场景中表现突出
  4. 比较次数统计显示:
  • 最好情况下(已有序),插入排序和冒泡排序优势明显
  • 最坏情况下(逆序),所有算法比较次数接近理论最大值
  • 随机数据中,插入排序通常表现最佳

理解这些基础排序算法的原理及优化策略,不仅有助于算法面试准备,更能培养对算法效率的直观感知。在实际开发中,应根据数据规模和特性选择合适的排序策略。

关注我!!🫵持续为你带来Python算法相关内容。

相关推荐
瑞雪兆丰年兮19 分钟前
数学实验(Matlab语言环境和线性代数实验)
算法·数学建模·matlab·数学实验
烨然若神人~1 小时前
算法训练营第十一天|150. 逆波兰表达式求值、239. 滑动窗口最大值、347.前 K 个高频元素
算法
天天爱吃肉82181 小时前
机器学习经典算法:用决策树原理优化新能源汽车续航能力
算法·决策树·机器学习
金融小师妹1 小时前
AI技术视角:美联储信号与黄金动态的量化研究——基于多模态数据分析框架
大数据·人工智能·算法
dot to one2 小时前
C++ 深入解析 数据结构中的 AVL树的插入 涉及的旋转规则
数据结构·c++·算法·visual studio·avl树
电院大学僧2 小时前
初学python的我开始Leetcode题8-4
python·算法·leetcode
代码不停2 小时前
Java数据结构——Queue
java·开发语言·数据结构
MeteorSaraphines2 小时前
第 14 届蓝桥杯 C++ 青少组省赛中 / 高级组真题解析
java·算法
行驶2 小时前
数据结构和算法
数据结构·算法
IT小鸟鸟2 小时前
LinkList 的底层数据结构及优缺点
java·数据结构·算法