一、简单排序算法
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 标记为 Trueswapped = 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 = ifor j in range(i+1, n):if arr[j] < arr[min_idx]:min_idx = jarr[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-1while j >=0 and key < arr[j]:arr[j+1] = arr[j]j -= 1arr[j+1] = keyreturn arr
-
适用场景:小规模数据或基本有序的数组。
二、分治排序算法
1. 快速排序(Quick Sort)
-
算法思想:分治法 + 基准值分区。选择一个基准值,小于基准值的放左边,大于基准值的放右边,每次比较之后,当下指针向中间移一位,若改变了元素位置则左右交替进行,为改变则继续比较此指针。
-
时间复杂度:
-
平均:O(n log n)
-
最坏(有序数组):O(n²)
-
-
稳定性:不稳定
-
代码实现:
def quick_sort(arr):if len(arr) <= 1:return arrpivot = 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 arrmid = len(arr) // 2left = merge_sort(arr[:mid])right = merge_sort(arr[mid:])return merge(left, right)def merge(left, right):result = []i = j = 0while i < len(left) and j < len(right):if left[i] <= right[j]:result.append(left[i])i += 1else:result.append(right[j])j += 1result += 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] += 1sorted_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 + 1buckets = [[] for _ in range(bucket_count)]for num in arr:idx = (num - min_val) // bucket_sizebuckets[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 = ileft = 2*i + 1right = 2*i + 2if left < n and arr[left] > arr[largest]:largest = leftif right < n and arr[right] > arr[largest]:largest = rightif 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²) | 稳定 | 小规模或基本有序数据 | 简单排序题 |