0x04 排序算法

#SortingAlgorithms

Review

  1. 2021/02/22
  2. 2024-09-08 08:08

[!Summary] 经典排序算法

  1. 冒泡排序
  2. 选择排序
  3. 插入排序
  4. 希尔排序
  5. 归并排序
  6. 快速排序
  7. 堆排序
  8. 计数排序
  9. 桶排序
  10. 基数排序
  11. 快排优化
  12. 拓扑排序

一、Introduction #

稳定排序:值相同的元素,排序后顺序不变 不稳定排序:值相同的元素,排序后顺序

NameBestAverageWorstMemoryStableComments
Bubble sortn$n²$1#Stable
Insertion sortn1#Stable
Shell sortn log(n)depends on gap sequencen (log(n))21#No-Stable
Selection sort1#No-Stable
Merge sortn log(n)n log(n)n log(n)n#Stable
Quick sortn log(n)n log(n)log(n)#No-StableQuicksort is usually done in-place with O(log(n)) stack space
Heap sortn log(n)n log(n)n log(n)1#No-Stable
Counting sortn + rn + rn + rn + r#Stabler - biggest number in array
Radix sortn * kn * kn * kn + k#Stablek - length of longest key

总结 #

时间复杂度 O($n^2$) 的算法

  1. 冒泡排序
  2. 选择排序 #No-Stable
  3. 插入排序
  4. 希尔排序 #No-Stable

时间复杂度 O($nlogn$) 的排序算法

  1. 快速排序 #No-Stable
  2. 归并排序
  3. 堆排序 #No-Stable

时间复杂度为线性的排序算法

  1. 计数排序
  2. 桶排序
  3. 基数排序

插入排序的时间复杂度是 O($n^2$),其中 n 是链表的长度。时间复杂度是 O($nlogn$) 的排序算法包括归并排序、堆排序和快速排序(快速排序的最差时间复杂度是 O($n^2$)),其中最适合链表的排序算法是归并排序

二、详细介绍 #

2.1、冒泡排序 #

原理:反复遍历数组,每次比较相邻的两个元素,如果顺序错误就交换它们。 优点:实现简单。 缺点:效率较低,时间复杂度为O($n^2$)。

冒泡排序(Bubble sort)优化 #

  • isSorted
  • sortBorder
  • 鸡尾酒排序:第一轮从左到右,第二轮从右到左,第三轮从左到右。。。主要应用于大部分有序的列表,能减少排序回合数

2.2、选择排序 #

  • 原理:每次找到未排序部分中的最小(或最大)元素,将其放到已排序部分的末尾。
  • 优点:数据移动次数较少。
  • 缺点:时间复杂度也是O($n^2$)。

2.3、插入排序 #

  • 原理:将一个待排序的元素,按其大小插入到一个已经排好序的有序数列中,从而得到一个新的、个数加1的有序数列。
  • 优点:对于部分有序的数组效率较高。
  • 缺点:平均时间复杂度为O($n^2$)。

2.4、希尔排序 #

  • 原理:插入排序的改进版,通过将数组分成多个子数组,对每个子数组进行插入排序,然后逐渐减小间隔重新分组,直到整个数组有序。
  • 优点:比插入排序效率高。
  • 缺点:时间复杂度分析比较复杂,取决于增量序列的选择。

2.5、归并排序 #

  • 原理:将待排序序列分成若干个子序列,每个子序列是有序的。然后将这些子序列两两合并成新的有序子序列,直到合并成一个大的有序序列。
  • 优点:稳定排序,时间复杂度为$O(nlogn)$。
  • 缺点:需要额外的空间。

2.6、快速排序 #

  • 原理:通过一趟排序将待排序列分割成两个子序列,其中一个子序列中所有元素均比另一个子序列中的所有元素小。然后对这两个子序列分别进行快速排序,整个排序过程可以递归进行,直到每个子序列只有一个元素或者为空。
  • 优点:平均时间复杂度为O($nlogn$),是常用的排序算法
  • 缺点:不稳定排序,最坏情况(不平衡)时间复杂度为O($n^2$)。

partition的选择可以优化:

  1. 选择最右元素
  2. 选择最左元素
  3. 选择中间元素
  4. 选择随机元素

快排优化 #

  1. 双路快速排序:双路快速排序算法是随机化快速排序的改进版本,partition 过程使用两个索引值(i、j)用来遍历数组,将 <v 的元素放在索引i所指向位置的左边,而将 >v 的元素放在索引j所指向位置的右边,v 代表标定值。
  2. 三路快速排序:

2.7、堆排序 #

  • 原理:将待排序序列构造成一个大顶堆或小顶堆,每次取出堆顶最大的(或最小的)元素,然后调整堆,使其仍然是一个堆,直到堆为空。
  • 优点:时间复杂度为O($nlogn$)。
  • 缺点:不稳定排序。

2.8、计数排序 #

  • 原理:假设输入的元素都是非负整数,且知道输入元素的范围。通过一个辅助数组,计算每个输入元素的个数,然后根据计数数组来重构输出数组。
  • 优点:时间复杂度为O(n+k),其中k是输入元素的范围。
  • 缺点:空间复杂度为O(k),适用于数据范围较小的场景。

2.9、桶排序 #

  • 原理:将数据分到多个桶中,每个桶再分别排序,最后将各个桶中的数据依次取出,得到有序的序列。
  • 优点:时间复杂度可以达到O(n),适用于数据分布比较均匀的情况。
  • 缺点:需要额外的空间。

2.10、基数排序 #

  • 原理:按照低位优先(或高位优先)的原则,将整数按个位、十位、百位…进行分别排序。
  • 优点:稳定排序,时间复杂度为O($d*n$),其中d是数字的位数。
  • 缺点:适用于整数排序。

Reference #