返回

排序算法和数据结构中的六种算法思想和应用

前端

从基础到精通,从掌握到实现,排序算法无疑是每个程序员必备的技能。作为一名资深程序员,我在多年的编程实践中总结了6种最常见的排序算法,并将其封装成了一套全面的算法体系。

本文将逐一介绍这6种排序算法的思想、时间复杂度、空间复杂度和稳定性,并提供每种算法的实现代码。通过阅读本文,你将对排序算法有更深入的了解,以便在实际编程中根据具体问题选择合适的算法。

1. 选择排序

选择排序的思想非常简单,它从待排序的数组中选择最小的元素,然后将其与第一个元素交换,依次类推,直到数组中的所有元素都被排序好。

时间复杂度:O(n^2)

空间复杂度:O(1)

稳定性:不稳定

def selection_sort(arr):
  for i in range(len(arr) - 1):
    min_index = i
    for j in range(i + 1, len(arr)):
      if arr[j] < arr[min_index]:
        min_index = j
    arr[i], arr[min_index] = arr[min_index], arr[i]

2. 冒泡排序

冒泡排序的思想也非常简单,它不断地比较相邻的两个元素,如果前一个元素大于后一个元素,则将它们交换,依次类推,直到数组中的所有元素都被排序好。

时间复杂度:O(n^2)

空间复杂度:O(1)

稳定性:稳定

def bubble_sort(arr):
  for i in range(len(arr) - 1):
    for j in range(len(arr) - i - 1):
      if arr[j] > arr[j + 1]:
        arr[j], arr[j + 1] = arr[j + 1], arr[j]

3. 插入排序

插入排序的思想是将一个元素插入到已经排序好的数组中,使其保持有序。具体来说,从待排序的数组中选择一个元素,然后将其与已经排序好的数组中的元素逐一比较,找到合适的位置将该元素插入到数组中。

时间复杂度:O(n^2)

空间复杂度:O(1)

稳定性:稳定

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

4. 希尔排序

希尔排序是插入排序的一种改进算法,它通过将数组分割成多个子数组,然后分别对每个子数组进行插入排序,最后将子数组合并成一个有序的数组。

时间复杂度:O(nlogn)

空间复杂度:O(1)

稳定性:不稳定

def shell_sort(arr):
  gap = len(arr) // 2
  while gap > 0:
    for i in range(gap, len(arr)):
      key = arr[i]
      j = i
      while j >= gap and key < arr[j - gap]:
        arr[j] = arr[j - gap]
        j -= gap
      arr[j] = key
    gap //= 2

5. 快速排序

快速排序是一种分治算法,它通过将数组分割成两个子数组,然后分别对两个子数组进行排序,最后将两个子数组合并成一个有序的数组。

时间复杂度:O(nlogn)

空间复杂度:O(logn)

稳定性:不稳定

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)

6. 归并排序

归并排序也是一种分治算法,它通过将数组分割成两个子数组,然后分别对两个子数组进行排序,最后将两个子数组合并成一个有序的数组。

时间复杂度:O(nlogn)

空间复杂度:O(n)

稳定性:稳定

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):
  merged = []
  left_index = 0
  right_index = 0
  while left_index < len(left) and right_index < len(right):
    if left[left_index] <= right[right_index]:
      merged.append(left[left_index])
      left_index += 1
    else:
      merged.append(right[right_index])
      right_index += 1
  merged.extend(left[left_index:])
  merged.extend(right[right_index:])
  return merged