返回

揭开代码王国中的宝藏:应届生掌握的十大排序算法

前端

排序算法:算法世界里的寻宝之旅

在算法的世界中,排序算法犹如一颗颗璀璨的明珠,照亮了无序数据的茫茫海洋。它们可以将混乱无章的数据变为井然有序的序列,如同将散落的宝石一颗颗串联起来,呈现出清晰而有意义的图景。

对于踏入代码王国的应届生来说,掌握排序算法是不可或缺的一把钥匙。这些算法是数据结构与算法课程中的基石,也是面试官的宠儿。掌握这些算法,不仅可以轻松应对面试,更能让你在实际工作中游刃有余,成为一名优秀的程序员。

排序算法的殿堂

算法世界里的排序算法可谓是种类繁多,各领风骚。从简单的冒泡排序和选择排序,到高效的归并排序和快速排序,再到适用于特定场景的桶排序和基数排序,每种算法都有其独特的优势和适用场景。

冒泡排序:简单易懂,基础扎实

冒泡排序是排序算法中最简单的一种,它通过不断比较相邻元素的大小,将较大的元素“浮”到数组末尾,就像气泡一样从底部逐渐上升到水面。虽然冒泡排序的效率不高,但它易于理解和实现,是学习排序算法的良好起点。

代码示例:

def bubble_sort(arr):
  """
  冒泡排序算法

  参数:
    arr:待排序的数组

  返回:
    排序后的数组
  """
  n = len(arr)
  for i in range(n):
    for j in range(0, n - i - 1):
      if arr[j] > arr[j + 1]:
        arr[j], arr[j + 1] = arr[j + 1], arr[j]

  return arr

选择排序:选出最优,逐个击破

选择排序与冒泡排序类似,也是通过不断比较元素的大小来进行排序。但它每次都会找到数组中最小或最大的元素,并将其放置在相应的位置。选择排序比冒泡排序效率稍高,但依然不是最优的排序算法。

代码示例:

def selection_sort(arr):
  """
  选择排序算法

  参数:
    arr:待排序的数组

  返回:
    排序后的数组
  """
  n = len(arr)
  for i in range(n):
    min_idx = i
    for j in range(i + 1, n):
      if arr[j] < arr[min_idx]:
        min_idx = j

    arr[i], arr[min_idx] = arr[min_idx], arr[i]

  return arr

插入排序:有序插入,井然有序

插入排序的思路很简单,就像我们在生活中整理扑克牌一样,将一张张牌有序地插入到已排序的序列中。插入排序的效率比冒泡排序和选择排序都要高,尤其是当数据量较小或接近有序时,其性能优势更加明显。

代码示例:

def insertion_sort(arr):
  """
  插入排序算法

  参数:
    arr:待排序的数组

  返回:
    排序后的数组
  """
  n = len(arr)
  for i in range(1, n):
    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

希尔排序:分组优化,高效提升

希尔排序是插入排序的改进版,它通过分组的方式将数据进行排序,从而提高排序效率。希尔排序先将数据分成较小的组,对每个组进行插入排序,然后再逐渐增大组的规模,直到整个数组有序。希尔排序的效率比插入排序更高,尤其是在处理大数据量时。

代码示例:

def shell_sort(arr):
  """
  希尔排序算法

  参数:
    arr:待排序的数组

  返回:
    排序后的数组
  """
  n = len(arr)
  gap = n // 2

  while gap > 0:
    for i in range(gap, n):
      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

  return arr

归并排序:分而治之,征服天下

归并排序是另一种高效的排序算法,它采用“分而治之”的思想,将数组不断分解成较小的子数组,然后对每个子数组进行排序,最后再将排序后的子数组合并成一个有序的数组。归并排序的效率很高,时间复杂度为O(n log n),是许多实际场景中的首选排序算法。

代码示例:

def merge_sort(arr):
  """
  归并排序算法

  参数:
    arr:待排序的数组

  返回:
    排序后的数组
  """
  n = len(arr)
  if n <= 1:
    return arr

  mid = n // 2
  left_half = merge_sort(arr[:mid])
  right_half = merge_sort(arr[mid:])

  return merge(left_half, right_half)

def merge(left, right):
  """
  合并两个排序好的子数组

  参数:
    left:左子数组
    right:右子数组

  返回:
    合并后的有序数组
  """
  i = 0
  j = 0
  merged = []

  while i < len(left) and j < len(right):
    if left[i] < right[j]:
      merged.append(left[i])
      i += 1
    else:
      merged.append(right[j])
      j += 1

  while i < len(left):
    merged.append(left[i])
    i += 1

  while j < len(right):
    merged.append(right[j])
    j += 1

  return merged

快速排序:随机漫步,快速制胜

快速排序也是一种高效的排序算法,它采用“随机漫步”的思想,通过随机选取一个元素作为枢轴,将数组分为两部分,然后分别对这两部分进行排序。快速排序的效率很高,时间复杂度为O(n log n),但它对数据分布比较敏感,在某些情况下可能会退化为O(n^2)的效率。

代码示例:

def quick_sort(arr):
  """
  快速排序算法

  参数:
    arr:待排序的数组

  返回:
    排序后的数组
  """
  n = len(arr)
  if n <= 1:
    return arr

  pivot = arr[n // 2]
  left = []
  right = []

  for i in range(n):
    if arr[i] < pivot:
      left.append(arr[i])
    elif arr[i] > pivot:
      right.append(arr[i])

  return quick_sort(left) + [pivot] + quick_sort(right)

堆排序:建堆取顶,有序成型

堆排序是一种基于堆数据结构的排序算法。它首先将数组构建成一个堆,然后不断从堆顶取出最大或最小的元素,并将其放置在数组的尾部。堆排序的效率很高,时间复杂度为O(n log n),并且在处理大数据量时具有较好的性能。

代码示例:

def heap_sort(arr):
  """
  堆排序算法

  参数:
    arr:待排序的数组

  返回:
    排序后的数组
  """
  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[0], arr[i] = arr[i], arr[0]
    heapify(arr, i, 0)

  return arr

def heapify(arr, n, i):
  """
  维护最大堆

  参数:
    arr:待维护的数组
    n:数组长度
    i:当前元素的索引
  """
  largest = i
  left = 2 * i + 1
  right = 2 * i + 2

  if left < n and arr[left] >