写在前面
最近也看了一些面经一些总结,排序是出现的频率最高的。今天就来总结一下最常出现的几个排序算法。包括Array
对象自带的sort()
方法,冒泡排序(BubbleSort
),快速排序(QuickSort
),选择排序(SeletionSort
),插入排序(InsertSort
)。本文主要是直接丢代码,不做过多解释,毕竟基本都是数据结构的知识。
算法复杂度
排序方式 | 平均 | 最坏 | 最好 | 空间 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O(n²) | O(n²) | O(n) | O(1) | 稳定 |
快速排序 | O(nlogn) | O(n²) | O(nlogn) | O(logn) | 不稳定 |
选择排序 | O(n²) | O(n²) | O(n²) | O(1) | 不稳定 |
插入排序 | O(n²) | O(n²) | O(n) | O(1) | 稳定 |
堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不稳定 |
归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | 稳定 |
Array.sort()
代码:
1 | const arr = [22,12,4,45,3,87,77,43,55,42]; |
冒泡排序(BubbleSort)
代码
1 | const arr = [22,12,4,45,3,87,77,43,55,42]; |
复杂度
- 时间复杂度O(n²)。
- 空间复杂度O(1)。
- 是稳定排序。
改进,时间复杂度为O(n)
- 加一个标志位,如果没有进行交换,将标志位设置为
false
,表示排序完成。 - 记录最后一次交换的位置,因为最后一次交换的数,是在这一次排序当中最大的数,之后的数都比它大。在最佳状态下,时间复杂度也会缩到O(n)。
快速排序(QuickSort)
代码
1 | //思路:找到一个基数,然后将比基数小的数放在基数的左边,将比基数大的放在基数的右边。 |
复杂度
- 时间复杂度:O(nlogn)。
- 空间复杂度:O(logn)。
- 是不稳定排序。
选择排序(SelectionSort)
代码
1 | //思路:第一遍,从数组中选出最小的,与第一个元素进行交换; |
复杂度
- 时间复杂度O(n²)。
- 空间复杂度O(1)。
- 该排序是不稳定排序。
插入排序(InsertSort)
代码
1 | //思路:首先,循环原数组,然后将当前位置的元素,插入到之前已排好的数组中,依次操作。 |
复杂度
- 时间复杂度O(n²)。
- 空间复杂度O(1)。
- 该排序是稳定排序。
堆排序
1 | //构造大顶堆 |
归并排序
归并排序的算法思路是,将两个有序的数组合并为一个有序数组往往比直接处理一个无序数组容易。为此,归并排序要创建n个只有一个元素的列表,其中n为要排序的列表的长度,然后再将这些列表合并为单个有序列表。
1 | let arr = [22,23,34,12,123,5,67,44,32]; |
复杂度
- 时间复杂度O(nlogn)。
- 空间复杂度O(n)。
- 该排序是稳定排序。
常见代码题
ajax
1 | //ajax请求 |
字符串翻转
1 | //字符串翻转 |
二分查找
1 | //二分查找 |
大数相加
1 | //大数相加 |
实现bind
1 | //实现bind |
继承
1 | //继承 |
二叉排序树
1 | /** |
排序
1 | //sort |