快速排序为 O(nlogn) 时间复杂度的算法,是一种不稳定的算法,最坏的情况下会退化成 O(n^2) 的时间复杂度。快速排序其实类似于二叉树的前序遍历。
方法一
算法思路,假设需要排序的数组为: “6 1 2 7 9 3 4 5 10 8”:
- 分别从初始序列“6 1 2 7 9 3 4 5 10 8”两端开始“探测”
- 先从右往左找一个小于 6 的数,再从左往右找一个大于 6 的数,然后交换它们
- 这里可以用两个变量 i 和 j,分别指向序列最左边和最右边。当 i 与 j 相遇的时候,将准基数 6 和 相遇点索引交换(这里是3),交换之后序列如下:“3 1 2 5 4 6 9 7 10 8”,6 左边的数都小于等于 6,6右边的数都大于等于 6
- 之后再以 6 为分界点,拆成 2 个序列,继续重复上面的操作,直到不可拆分出新的子序列为止,数组就变成有序的了
代码如下:
1 | function quickSortOne(arr, left, right) { |
方法二
算法思路:
- 每次在当前需要排序的数组选择一个元素,以这个元素为基点,例如 “4 6 2 3 1 5 7 8” 这个数组,选择 4 作为基点
- 之后想办法把 4 这个元素挪到一个位置,使 4 之前的位置都小于 4 ,4 之后的所有元素都是大于 4 的
- 之后我们要做的事情,是对小于 4 的这部分字数组和大于 4 的字数组分别继续使用快速排序的思路排序,逐渐递归下去,完成排序
代码如下:
1 | // 对arr[l...r]范围内的数组进行插入排序 |
方法三
对于上面第一种和第二种方法,对于有大量重复健值的数组排序,很容易使数组退化成 O(n^2) 复杂度的算法,对于此,我们可以用另外一种快速排序方法,也就是:三路快排(Quick Sort 3 Ways)。
算法思想:
之前的排序方法都是把数组分成 2 部分,小于基数 v 和大于基数 v,而三路快排则是把数组分为三部分:小于 v, 等于 v 和 大于 v。这样我们在对比的过程种,对于等于 v 的部分就不需要操作,只需要操作小于和大于 v 的数值。
代码如下:
1 | // 三路快速排序处理 arr[l...r] |