面试 - 排序算法总结


在这里插入图片描述

冒泡排序(BubbleSort) O(n2)

基本思想:两个数比较大小,较大的数下沉,较小的数冒起来。

选择排序(SelctionSort)

在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换;
第二次遍历n-2个数,找到最小的数值与第二个元素交换;
。。。
第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成。

插入排序(Insertion Sort)

在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

希尔排序(Shell Sort)

在要排序的一组数中,根据某一增量分为若干子序列,并对子序列分别进行插入排序。
然后逐渐将增量减小,并重复上述过程。直至增量为1,此时数据序列基本有序,最后进行插入排序。

快速排序(Quicksort)

基本思想:(分治)

先从数列中取出一个数作为key值;
将比这个数小的数全部放在它的左边,大于或等于它的数全部放在它的右边;
对左右两个小数列重复第二步,直至各区间只有1个数。

归并排序(Merge Sort)

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用。
首先考虑下如何将2个有序数列合并。这个非常简单,只要从比较2个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。

堆排序(HeapSort)

先把数组构造成一个大顶堆(父亲节点大于其子节点),然后把堆顶(数组最大值,数组第一个元素)和数组最后一个元素交换,这样就把最大值放到了数组最后边。把数组长度n-1,再进行构造堆,把剩余的第二大值放到堆顶,输出堆顶(放到剩余未排序数组最后面)。依次类推,直至数组排序完成。

基数排序(RadixSort)

BinSort想法非常简单,首先创建数组A[MaxValue];然后将每个数放到相应的位置上(例如17放在下标17的数组位置);最后遍历数组,即为排序后的结果。


参考

https://www.runoob.com/w3cnote/sort-algorithm-summary.html
https://www.cnblogs.com/maluning/p/7944809.html

### 冒泡排序 冒泡排序是一种简单的排序算法,它通过重复地遍历要排序的列表,比较相邻的元素并交换它们的位置来工作。如果某次遍历中没有发生任何交换,说明列表已经有序,可以提前结束排序。冒泡排序的时间复杂度为 $O(n^2)$,空间复杂度为 $O(1)$,并且是稳定的排序算法[^1]。 #### Java 实现示例 ```java public static void main(String[] args) { int[] arr = {1, 2, 5, 3, 7, 9, 6, 4, 0, 9, 5}; boolean flag = false; // 表示没有发生过交换 for (int i = 0; i < arr.length - 1; i++) { for (int j = 0; j < arr.length - 1 - i; j++) { if (arr[j] > arr[j + 1]) { int t = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = t; flag = true; // 发生交换 } } if (!flag) break; else flag = false; // 重置flag, 进行下次判断 } for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } } ``` ### 选择排序 选择排序的基本思想是在未排序序列中找到最小(或最大)的元素,然后将其放到已排序序列的末尾。该算法的时间复杂度也是 $O(n^2)$,空间复杂度为 $O(1)$,但它是不稳定的排序算法[^1]。 #### Java 实现示例 ```java public static void main(String[] args) { int[] arr = {1, 2, 5, 3, 7, 9, 6, 4, 0, 9, 5}; int min = 0; for (int i = 0; i < arr.length; i++) { min = i; for (int j = i + 1; j < arr.length; j++) { if (arr[min] > arr[j]) { min = j; } } int tmp = arr[min]; arr[min] = arr[i]; arr[i] = tmp; } for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } } ``` ### 快速排序 快速排序是一种分治策略的排序算法,它通过选定一个基准元素,将数组分成两个子数组,一个子数组的所有元素都比基准小,另一个子数组的所有元素都比基准大,然后递归地在这两个子数组上应用同样的快速排序过程。快速排序的平均时间复杂度为 $O(n \log n)$,最坏情况下为 $O(n^2)$,空间复杂度为 $O(\log n)$,并且是不稳定的排序算法[^2]。 ### 插入排序 插入排序通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序的时间复杂度为 $O(n^2)$,空间复杂度为 $O(1)$,并且是稳定的排序算法[^4]。 ### 归并排序 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个典型应用。归并排序的时间复杂度为 $O(n \log n)$,空间复杂度为 $O(n)$,并且是稳定的排序算法[^4]。 ### 希尔排序 希尔排序是插入排序的一种更高效的改进版本,也被称为缩小增量排序。它的基本思想是将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次插入排序。希尔排序的时间复杂度介于 $O(n \log n)$ 和 $O(n^{1.5})$ 之间,空间复杂度为 $O(1)$,并且是不稳定的排序算法[^4]。 ### 计数排序 计数排序是一种非比较型整数排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序算法,计数排序要求输入的数据是由一个确定范围内的整数组成。计数排序的时间复杂度为 $O(n+k)$,其中 $k$ 是输入数据的范围,空间复杂度也为 $O(n+k)$,并且是稳定的排序算法[^4]。 ### 基数排序 基数排序是一种非比较型整数排序算法,它将整数按位数切割成不同的数字,然后按每个位数进行排序。基数排序的时间复杂度为 $O(nk)$,其中 $k$ 是输入数据的最大位数,空间复杂度为 $O(k)$,并且是稳定的排序算法[^4]。 以下是这些排序算法的一些关键特性总结: | 排序算法 | 平均时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 是否稳定 | |----------|----------------|----------------|------------|----------| | 冒泡排序 | $O(n^2)$ | $O(n^2)$ | $O(1)$ | 是 | | 选择排序 | $O(n^2)$ | $O(n^2)$ | $O(1)$ | 否 | | 插入排序 | $O(n^2)$ | $O(n^2)$ | $O(1)$ | 是 | | 快速排序 | $O(n \log n)$| $O(n^2)$ | $O(\log n)$ | 否 | | 归并排序 | $O(n \log n)$| $O(n \log n)$| $O(n)$ | 是 | | 希尔排序 | $O(n \log n)$到 $O(n^{1.5})$ | $O(n^{1.5})$ | $O(1)$ | 否 | | 计数排序 | $O(n+k)$ | $O(n+k)$ | $O(n+k)$ | 是 | | 基数排序 | $O(nk)$ | $O(nk)$ | $O(k)$ | 是 | ### 相关问题 1. 冒泡排序如何优化以提高效率? 2. 快速排序与归并排序的主要区别是什么? 3. 哪些排序算法适合处理大数据集? 4. 为什么计数排序和基数排序被认为是线性时间复杂度的排序算法? 5. 插入排序和希尔排序之间有何联系与区别? [^1]: 提供了冒泡排序和选择排序的基本概念及其实现。 : 描述了快速排序的基本思想。 [^3]: 展示了冒泡排序的另一种实现方式。 [^4]: 总结了多种排序算法的时间复杂度、空间复杂度以及稳定性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值