cevalokas

personal website

Not because they are easy, but because they are hard.


常见排序

目录

1. 冒泡排序(Bubble Sort)

算法步骤

  1. 从数组的第一个元素开始,比较相邻的两个元素。如果前一个元素大于后一个元素,则交换它们的位置。
  2. 对每一对相邻元素重复这个操作,从数组的开始到结尾。这一步骤会将最大的元素“冒泡”到数组的最后位置。
  3. 忽略已经排序好的部分(最后一个元素),重复以上步骤,直到整个数组有序。

性能分析

  • 时间复杂度
    • 最佳情况:当数组已经有序时,只需进行一次遍历即可完成排序,时间复杂度为 $O(n)$。
    • 平均情况和最坏情况:在平均情况下和最坏情况下,冒泡排序的时间复杂度为 $O(n^2)$,因为需要对每一对元素进行比较并可能进行交换。
  • 空间复杂度:$O(1)$,冒泡排序是就地排序算法,只需要常量级的额外空间。

  • 稳定性:冒泡排序是稳定的排序算法,因为在元素相等时不会交换它们的位置。

2. 选择排序(Selection Sort)

算法步骤

  1. 从未排序部分中选择最小(或最大)的元素,将其与未排序部分的第一个元素交换。
  2. 将已排序部分向后移动一个位置,继续在未排序部分中选择最小(或最大)的元素,进行交换。
  3. 重复上述步骤,直到整个数组有序。

性能分析

  • 时间复杂度
    • 最佳情况、平均情况和最坏情况:选择排序的时间复杂度始终为 $O(n^2)$,因为每次选择最小元素都需要遍历未排序部分。
  • 空间复杂度:$O(1)$,选择排序也是就地排序算法,不需要额外的存储空间。

  • 稳定性:选择排序是不稳定的排序算法,因为当两个相等的元素存在时,选择排序可能会改变它们的相对顺序。

3. 插入排序(Insertion Sort)

算法步骤

  1. 从第二个元素开始,将该元素与之前的元素进行比较。
  2. 如果当前元素小于之前的元素,将之前的元素后移一位,继续比较,直到找到合适的位置插入当前元素。
  3. 重复步骤2,直到数组有序。

性能分析

  • 时间复杂度
    • 最佳情况:当数组已经有序时,只需要进行 $O(n)$ 次比较,时间复杂度为 $O(n)$。
    • 平均情况和最坏情况:插入排序的时间复杂度为 $O(n^2)$,因为每次插入操作可能需要在已排序部分中进行多次比较和移动。
  • 空间复杂度:$O(1)$,插入排序是就地排序算法。

  • 稳定性:插入排序是稳定的,因为相同元素的相对顺序不会被改变。

4. 快速排序(Quick Sort)

算法步骤

  1. 从数组中选择一个“基准”(pivot),通常选择第一个元素、最后一个元素或随机选择。
  2. 重新排序数组,将所有比基准小的元素放到基准的左边,所有比基准大的元素放到基准的右边。此时,基准元素在其正确的位置上。
  3. 递归地对基准左边的子数组和右边的子数组进行快速排序。
  4. 重复上述步骤,直到整个数组有序。

性能分析

  • 时间复杂度
    • 最佳情况和平均情况:当基准总能将数组平衡分割时,时间复杂度为 $O(n \log n)$。
    • 最坏情况:当基准每次都选择了数组中的最大或最小值,时间复杂度会退化为 $O(n^2)$。
  • 空间复杂度:快速排序的空间复杂度为 $O(\log n)$,这是由于递归调用堆栈的深度。

  • 稳定性:快速排序是不稳定的,因为在基准划分过程中,元素的相对顺序可能会改变。

5. 归并排序(Merge Sort)

算法步骤

  1. 将数组递归地分成两半,直到每个子数组只包含一个元素。
  2. 依次将子数组两两合并,并在合并过程中对元素进行排序。
  3. 重复上述步骤,直到所有子数组合并为一个有序数组。

性能分析

  • 时间复杂度:归并排序的时间复杂度始终为 $O(n \log n)$,因为它总是将数组分成两半并合并。

  • 空间复杂度:归并排序的空间复杂度为 $O(n)$,因为它需要额外的数组来存储合并结果。

  • 稳定性:归并排序是稳定的排序算法,因为在合并过程中不会改变相同元素的相对顺序。

6. 堆排序(Heap Sort)

算法步骤

  1. 将数组构造成一个最大堆(或最小堆),这是一个完全二叉树,满足堆的性质。
  2. 将堆顶元素(最大或最小)与最后一个元素交换,将堆的大小减一。
  3. 调整堆以维持堆的性质,继续交换堆顶元素和最后一个元素,直到堆大小为1。

性能分析

  • 时间复杂度:堆排序的时间复杂度为 $O(n \log n)$,因为构建堆需要 $O(n)$,而调整堆的过程需要 $O(\log n)$。

  • 空间复杂度:堆排序的空间复杂度为 $O(1)$,因为它在原地进行排序。

  • 稳定性:堆排序是不稳定的排序算法,因为在调整堆的过程中,可能会改变相同元素的相对顺序。

对于小规模数据集,插入排序可能是个不错的选择,而对于大规模数据集,快速排序和归并排序通常表现更佳。