九种排序方法(冒泡、选择、插入、希尔、归并、快速、计数、桶、基数)
一、冒泡排序
冒泡排序的名字来源于这个过程:就像水中的气泡从底部向上浮到水面一样,较大的元素会逐步移动到数组的末尾。
我们使用「冒泡」的方式来模拟一下这个过程:
- 将数组元素想象成大小不同的「泡泡」,值越大的元素「泡泡」越大。
- 从左到右依次比较相邻的两个元素。
- 如果左侧元素大于右侧元素,则交换位置。
- 每完成一趟遍历,最大的元素就会「浮」到最右侧。
算法步骤
对于长度为𝑛 的数组,冒泡排序的步骤如下:
第 1 趟冒泡:对前𝑛 个元素依次比较相邻元素,将较大的元素向右交换,最终使最大值移动到数组末尾(第𝑛 个位置)。
- 比较第 1 个和第 2 个元素,如果前者大于后者则交换。
- 比较第 2 个和第 3 个元素,如果前者大于后者则交换。
- 以此类推,直到比较第𝑛 − 1 个和第𝑛 个元素。
- 完成后,最大元素已位于末尾。
第 2 趟冒泡:对前𝑛 − 1 个元素重复上述过程,将次大值移动到倒数第二个位置(第𝑛 − 1 个位置)。
- 比较第 1 个和第 2 个元素,如果前者大于后者则交换。
- 比较第 2 个和第 3 个元素,如果前者大于后者则交换。
- 以此类推,直到比较第𝑛 − 2 个和第𝑛 − 1 个元素。
完成后,次大元素已位于倒数第二位。
持续进行上述冒泡过程,每一趟比较的元素个数递减,直到某一趟未发生任何交换,说明数组已完全有序,排序结束。
以数组[5, 2, 3, 6, 1, 4] 为例,演示一下冒泡排序的算法步骤。

二、选择排序
选择排序(Selection Sort)基本思想是将数组分为两个区间:左侧为已排序区间,右侧为未排序区间。每趟从未排序区间中选择最小的元素,放到已排序区间的末尾。
算法步骤
假设数组长度为𝑛,选择排序的算法步骤如下:
- 初始状态:已排序区间为空,未排序区间为[0, 𝑛 − 1]。
- 第 𝑖 趟选择(𝑖 从 1 开始):
- 在未排序区间[𝑖 − 1, 𝑛 − 1] 中找到最小元素的位置𝑚𝑖𝑛_𝑖。
- 将位置𝑖 − 1 的元素与位置𝑚𝑖𝑛_𝑖 的元素交换。
- 此时[0, 𝑖 − 1] 为已排序区间,[𝑖, 𝑛 − 1] 为未排序区间。
- 重复步骤 2,直到未排序区间为空,排序完成。
以数组[5, 2, 3, 6, 1, 4] 为例,演示一下选择排序的算法步骤。




三、插入排序
插入排序(Insertion Sort)基本思想是将数组分为有序区间和无序区间,每次从无序区间取出一个元素插入到有序区间的正确位置。
算法步骤
假设数组nums长度为𝑛,算法步骤如下:
- 初始化:有序区间为[0, 0],无序区间为[1, 𝑛 − 1]
- 第 𝑖 趟插入(𝑖 从 1 到𝑛 − 1):
• 取出无序区间第一个元素nums[𝑖]
• 从右到左遍历有序区间,将大于nums[𝑖] 的元素右移一位
• 找到合适位置后插入nums[𝑖]
• 有序区间扩展为[0, 𝑖],无序区间变为[𝑖 + 1, 𝑛 − 1]
以数组[5, 2, 3, 6, 1, 4] 为例,演示一下插入排序的算法步骤。

四、希尔排序
希尔排序(Shell Sort)基本思想是通过设定不同的间隔(gap),将数组分组进行插入排序,然后逐步缩小间隔直至为 1,最终完成整个数组的排序。
算法步骤
假设数组长度为𝑛,算法步骤如下:
- 设定初始间隔gap = n / 2。
- 按间隔将数组分组,对每组进行插入排序。
- 缩小间隔gap = gap / 2。
- 重复步骤 2 ∼ 3,直到gap = 1。5. 最后对整个数组进行一次插入排序。
以数组[7, 2, 6, 8, 0, 4, 1, 5, 9, 3] 为例,演示一下希尔排序的算法步骤。

五、归并排序
归并排序(Merge Sort)基本思想是利用分治法,将数组递归地一分为二,直至每个子数组只包含一个元素。随后,将这些有序子数组两两合并,最终得到一个整体有序的数组。
算法步骤
假设数组的元素个数为 𝑛 个,则归并排序的算法步骤如下:
分解过程:递归地将当前数组平分为两部分,直到每个子数组只包含一个元素为止。
- 找到数组的中间位置 mid ,将数组划分为左、右两个子数组 left_nums 和 right_nums。
- 分别对 left_nums 和 right_nums 递归执行分解操作。
- 最终将原数组拆分为 𝑛 个长度为 1 的有序子数组。
归并过程:从长度为 1 的有序子数组开始,逐步将相邻的有序子数组两两合并,最终合并为一个长度为𝑛 的有序数组。
- 新建数组nums用于存放合并后的有序结果。
- 设置两个指针 left_𝑖 和 right_𝑖,分别指向 left_nums 和 right_nums 的起始位置。
- 比较两个指针所指元素,将较小者加入结果数组 nums ,并将对应指针后移一位。
- 重复上述操作,直到某一指针到达对应子数组末尾。
- 将另一个子数组剩余的所有元素依次加入结果数组 nums 。
- 返回合并后的有序数组 nums 。
以数组[0, 5, 7, 3, 1, 6, 8, 4] 为例,演示一下归并排序的算法步骤。

六、快速排序
快速排序(Quick Sort)基本思想:采用分治策略,选择一个基准元素,将数组分为两部分:小于基准的元素放在左侧,大于基准的元素放在右侧。然后递归地对左右两部分进行排序,最终得到有序数组。
算法步骤
快速排序的核心是 分区操作,具体步骤如下:
- 选择基准:从数组中选择一个元素作为基准值(通常选择第一个元素)
- 分区操作:
• 使用双指针法,左指针从数组开始,右指针从数组末尾
• 右指针向左移动,找到第一个小于基准值的元素
• 左指针向右移动,找到第一个大于基准值的元素
• 交换这两个元素
• 重复上述过程,直到左右指针相遇
• 将基准值放到正确位置(左右指针相遇处) - 递归排序:对基准值左右的两个子数组分别进行快速排序
以数组[4, 7, 5, 2, 6, 1, 3] 为例,先来演示一下快速排序的分区操作过程。




完成一次分区后,数组被分为三部分:左子数组、基准值、右子数组。然后递归地对左右子数组进行排序。

七、计数排序
计数排序(Counting Sort)基本思想是统计数组中每个元素出现的次数,然后根据统计信息将元素按顺序放置到正确位置,实现排序。
算法步骤
- 确定数值范围:找出数组中的最大值和最小值,计算数值范围。
- 创建计数数组:创建一个大小为数值范围的数组,用于统计每个元素出现的次数。
- 统计元素频次:遍历原数组,统计每个元素出现的次数。
- 计算累积频次:将计数数组转换为累积频次数组,表示每个元素在排序后数组中的位置。
- 逆序填充结果:逆序遍历原数组,根据累积频次将元素放入正确位置。
以数组[3, 0, 4, 2, 5, 1, 3, 1, 4, 5] 为例,演示一下计数排序的算法步骤。

八、桶排序
桶排序(Bucket Sort)是将待排序元素分散到多个桶中,对每个桶单独排序后合并。
算法步骤
- 确定桶的数量:根据待排序数组的数值范围,将其划分为𝑘 个桶,每个桶对应一个特定的区间。
- 元素分配:遍历数组,将每个元素根据其数值映射到所属的桶中。
- 桶内排序:对每个非空桶分别进行排序(可选用插入排序、归并排序、快速排序等算法)。
- 合并结果:按桶的顺序依次合并所有已排序的桶,得到最终有序数组。
以数组[39, 49, 8, 13, 22, 15, 10, 30, 5, 44] 为例,演示一下桶排序的算法步骤。

九、基数排序
基数排序(Radix Sort)基本思想是按照数字的每一位进行排序,从最低位到最高位,逐位比较。
算法步骤
基数排序算法可以采用「最低位优先法(Least Significant Digit First)」或者「最高位优先法(Most Significant Digit first)」。最常用的是「最低位优先法」。
下面我们以最低位优先法为例,讲解一下算法步骤。
- 确定最大位数:遍历数组元素,找到数组中最大值的位数。
- 从最低位(个位)开始,到最高位为止,逐位对每一位进行排序:
- 创建 10 个桶(每个桶分别代表 0 ∼ 9 中的一个数字)。
- 按照每个元素当前位上的数字,将元素放入对应桶中。
- 清空原始数组,然后按照桶的顺序依次取出对应元素,重新加入到数组中。
我们以[692, 924, 969, 503, 871, 704, 542, 436] 为例,演示一下基数排序的算法步骤。

各算法对比
| 排序算法 | 最好时间复杂度 | 平均时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 稳定性 |
|---|---|---|---|---|---|
| 冒泡排序 | O(n) | O(n²) | O(n²) | O(1) | ✅ 稳定 |
| 选择排序 | O(n²) | O(n²) | O(n²) | O(1) | ❌ 不稳定 |
| 插入排序 | O(n) | O(n²) | O(n²) | O(1) | ✅ 稳定 |
| 希尔排序 | O(n log n) ~ O(n) | 约 O(n^1.3) | O(n²) | O(1) | ❌ 不稳定 |
| 归并排序 | O(n log n) | O(n log n) | O(n log n) | O(n) | ✅ 稳定 |
| 快速排序 | O(n log n) | O(n log n) | O(n²) | O(log n) | ❌ 不稳定 |
| 计数排序 | O(n + k) | O(n + k) | O(n + k) | O(n + k) | ✅ 稳定 |
| 桶排序 | O(n + k) | O(n + k) | O(n²) | O(n + k) | 视实现而定 |
| 基数排序 | O(d(n + k)) | O(d(n + k)) | O(d(n + k)) | O(n + k) | ✅ 稳定 |

浙公网安备 33010602011771号