第七课: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算法相关内容。

相关推荐
大刀爱敲代码1 小时前
基础算法01——二分查找(Binary Search)
java·算法
大小胖虎2 小时前
数据结构——第六章:图
数据结构·笔记··最小生成树·拓扑排序·最短路径
HR Zhou5 小时前
群体智能优化算法-正弦余弦算法(Sine Cosine Algorithm, SCA,含Matlab源代码)
算法·机器学习·matlab·优化·群体智能优化
自信的小螺丝钉5 小时前
Leetcode 378. 有序矩阵中第 K 小的元素 二分查找
算法·leetcode·矩阵·二分查找
m0_735234606 小时前
蓝桥杯算法实战分享:算法进阶之路与实战技巧
算法·职场和发展·蓝桥杯
程序员老周6666 小时前
矩阵补充,最近邻查找
算法·机器学习·推荐算法
_GR6 小时前
2021年蓝桥杯第十二届C&C++大学B组真题及代码
c语言·数据结构·c++·算法·蓝桥杯
奋进的小暄6 小时前
贪心算法(11)(java)加油站
算法·贪心算法
lwewan7 小时前
26考研——图_图的基本概念(6)
数据结构·考研
tpoog7 小时前
[贪心算法]最长回文串 && 增减字符串匹配 && 分发饼干
算法·贪心算法