返回

AI领航:漫话归并排序与快速排序

前端

序言
欢迎来到算法与数据结构的进阶之旅!本文旨在用一种轻松诙谐的方式,为您阐述归并排序和快速排序这两大经典排序算法。

结识归并排序

原理:

  • 设想一个参差不齐的海绵体,将它均分成两部分。
  • 接着,把每部分的海绵再分成两半,依此类推,直到每个海绵体都变成一块。
  • 现在,按照大小依次把这些小海绵体合并起来,就得到了一个有序的海绵体。

流程:

  1. 将数组划为左右两部分
  2. 递归地对左右两部分进行排序
  3. 合并两部分为一个有序数组

复杂度:

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

邂逅快速排序

原理:

  • 挑选数组中一个“哨兵”值(通常是中间值)
  • 把比哨兵值小的数放左边,比哨兵值小的数放右边
  • 对左右两部分分别进行同样的快速排序

流程:

  1. 选择一个哨兵值
  2. 遍历数组,将比哨兵值小的数放左边,比哨兵值小的数放右边
  3. 递归地对左右两部分进行快速排序

复杂度:

  • 平均时间复杂度:O(n log n)
  • 空间复杂度:O(1)(不考虑递归栈)

算法比拼

归并排序 快速排序
原理 逐段分解、合并 哨兵分治、递归
时间复杂度 O(n log n) O(n log n)
空间复杂度 O(n) O(1)
适合场景 数组较大且有序度较低 数组较小或接近有序
优化技巧 迭代归并排序优化尾递归 通过优化减少哨兵值选择误差

代码实战

归并排序(python):

def MergeSort(arr: list) -> list:
  """归并排序"""

  def Merge(left: list, right: list) -> list:
    i, j, ans = 0, 0, []
    while i < len(left) and j < len(right):
      if left[i] <= right[j]:
        ans.append(left[i])
        i += 1
      else:
        ans.append(right[j])
        j += 1
    ans.append(left[i:])
    ans.append(right[j:])
    return ans

  if not arr:
    return []
  mid = len(arr) >> 1  # 右位移相当于 //2
  return Merge(MergeSort(arr[:mid]), MergeSort(arr[mid:]))

快速排序(python):

def Partition(arr: list, low: int, high: int) -> int:
  """快排切分"""
  i = low - 1
  pivot = arr[high]

  for j in range(low, high):
    if arr[j] <= pivot:
      i += 1
      arr[i], arr[j] = arr[j], arr[i]

  arr[i+1], arr[high] = arr[high], arr[i+1]
  return i+1

def quickSort(arr: list, low: int, high: int) -> None:
  """快速排序"""
  if low < high:
    pi = Partition(arr, low, high)
    
    # 递归调用
    if pi > 0 and pi < len(arr):
      arr[:pi], arr[pi+1:] = arr[pi-1:0:-1], arr[pi+1:]
      
    # 切割点左右快速排序
    
    if pi > 1:
      if pi-1 > 0:
        arr[:pi] = quickSort(arr[:pi], 0, pi-1)
      else:
        arr[pi] = quickSort([arr[pi]], 0, 0)
    
    if pi+1 < len(arr):
      if pi+1 < len(arr)-1:
        arr[pi+1:] = quickSort(arr[pi+1:], 0, len(arr)-pi-1)
      else:
        arr[pi+1:] = quickSort([arr[pi+1]], 0, 0)

进阶探讨

掌握了归并排序和快速排序的基本原理后,我们来看看如何进一步优化:

  • 迭代归并排序:优化递归,用循环代替递归
  • 快速排序哨兵优化:优化哨兵选择,如使用中位数、在区间内部选取多个哨兵值

总结

归并排序和快速排序可谓算法界的两大巨头,它们既经典又实用。无论是想高效排序大规模无序数据,还是在特定场景下寻求最优方案,它们都是不二之选。

掌握好这两大排序算法,算法进阶之旅才能走得更远,探索数据结构的奥秘也能更加得心应手!