冒泡排序
冒泡排序是一种简单的排序算法,通过重复比较相邻元素并交换它们的位置来将较大的元素“冒泡”到列表的末端。它的基本操作是两两比较和交换,直到整个列表排序完成。
希尔排序
希尔排序(Shell Sort)是一种插入排序的改进版本,旨在通过分组和逐渐减少这些组的间隔来提高排序效率。它的基本思想是将整个待排序数组分成若干个子数组,对这些子数组进行插入排序,然后逐步缩小间隔,直到最终进行一次普通的插入排序。希尔排序的步骤如下:
-
选择间隔(gap)序列:首先选择一个间隔序列(gap sequence),例如初始间隔较大的数值,然后逐步减小间隔,直到间隔为 1。
-
分组排序:对于每一个间隔值,将数组分为若干组,每组的元素在当前间隔下进行插入排序。例如,对于间隔为 5 的情况,将数组中的第1、6、11…个元素分为一组,第2、7、12…个元素分为另一组,以此类推。
-
缩小间隔:重复步骤 2,但使用较小的间隔值,直到间隔缩小到 1。
-
最终插入排序:当间隔为 1 时,对整个数组进行最终的插入排序。
希尔排序的时间复杂度通常比简单的插入排序更优,具体的性能依赖于间隔序列的选择。希尔排序的优点包括:
- 比直接插入排序效率更高,尤其是对于大规模数据。
- 算法实现简单,不需要额外的内存空间(就地排序)。
由于希尔排序的间隔序列选择的不同,算法的性能也会有所不同。最常见的间隔序列是希尔的原始序列和 Hibbard 序列。
归并排序
归并排序(Merge Sort)是一种基于分治法的排序算法。其基本步骤如下:
- 分割:将待排序数组分成两个大致相等的子数组。
- 递归排序:对这两个子数组递归地应用归并排序。
- 合并:将两个已排序的子数组合并成一个排序好的数组。
归并排序的优点包括:
- 稳定性:相同元素的相对位置不变。
- 时间复杂度:最坏、最好和平均情况时间复杂度均为 O(n log n)。
它的缺点是需要额外的空间来存储临时数组,因此空间复杂度为 O(n)。
快速排序
快速排序(Quick Sort)是一种高效的分治排序算法。其基本步骤如下:
- 选择枢轴:从数组中选择一个元素作为枢轴(pivot)。
- 分区:将数组重新排列,使得小于枢轴的元素位于枢轴左侧,大于枢轴的元素位于右侧。
- 递归排序:对枢轴左侧和右侧的子数组递归应用快速排序。
快速排序的优点包括:
- 时间复杂度:平均情况下为 O(n log n),在最佳情况下也为 O(n log n)。
- 空间复杂度:较低,通常为 O(log n)(递归栈深度)。
它的缺点是最坏情况下(例如在已经排序好的数组上进行排序)时间复杂度为 O(n^2)。
插入排序
插入排序(Insertion Sort)是一种简单的排序算法,适合于小规模数据的排序。其基本思想是将待排序的元素逐个插入到已经排好序的部分中。以下是插入排序的步骤:
-
初始状态:将数组分为两个部分,左边是已排序的部分,右边是未排序的部分。开始时,已排序部分只有第一个元素,未排序部分包含剩余的元素。
-
插入元素:从未排序部分取出一个元素,将其插入到已排序部分的适当位置。这个过程是通过比较并移动元素来完成的,以确保插入后的已排序部分仍然保持排序状态。
-
重复:重复步骤 2,直到未排序部分为空。
插入排序的具体过程如下:
- 从第二个元素开始,依次与已排序部分的元素进行比较。
- 通过移动已排序部分的元素,将目标元素插入到合适的位置。
优点:
- 简单易懂:算法实现简单。
- 稳定性:相同元素的相对位置不变。
- 适合小规模数据:对小规模数据或接近排序好的数据表现良好。
缺点:
- 时间复杂度:最坏和平均情况下时间复杂度为 O(n^2),这使得它在处理大规模数据时效率较低。
适用场景:
插入排序适用于数据量较小的情况,或者当数据已经部分排序时,插入排序的效率会比较高。
选择排序
选择排序(Selection Sort)是一种简单的排序算法,主要思想是通过不断选择未排序部分中的最小(或最大)元素,并将其放到已排序部分的末尾。具体步骤如下:
- 遍历未排序部分:从未排序部分中找到最小(或最大)元素。
- 交换位置:将找到的最小(或最大)元素与未排序部分的第一个元素交换位置。
- 缩小范围:将已排序部分扩大一个元素,未排序部分缩小一个元素。
- 重复:重复步骤 1 到 3,直到所有元素都被排序。
优点:
- 实现简单:算法简单直观,易于实现。
- 不需要额外的内存:排序在原数组中进行,不需要额外的存储空间。
缺点:
- 时间复杂度:最坏、最好和平均情况下时间复杂度均为 O(n^2),在处理大规模数据时效率较低。
- 稳定性:选择排序通常不是稳定的排序算法(即相同值的元素可能会改变相对位置)。
选择排序适用于数据量较小的情况,或者对稳定性要求不高的场景。