经典排序之快排

219 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

前言

快速排序通常也叫做快拍,是排序算法中很经典的一种排序方式,之所以经典是因为快排的时间复杂度一般为n*logn ,之所以说一般是因为在最差的情况下它的时间复杂度可能会变为n^2,这时候有人会问了,为什么存在n^2的情况还要用快排呢,原因有两个,一个就是出现n^2的几率比较小,还有一个关键的原因是快排的空间复杂度是O(1),这和其它的排序方式相比就剩了很多内存。下面来看一下代码的实现

function quicklySort(arr) {
    sortFun(arr, 0, arr.length - 1);
    return arr;
}

function sortFun(arr, left, right) {
    if (left >= right) return; //当左指针指向的下标小于等于右指针指向的下标的时候就可以退出递归了
    const mark = arr[right];//选右指针的指向的项当做标志,拿剩下的项和它做对比
    let i = left;
    for (let j = left; j < right; j++) {
        if (arr[j] <= mark) { //循环当中小于标志项的数字都往左进行交换
            exchange(arr, i, j) 
            i++;
        }
    }
exchange(arr, i, right);//当for循环结束后要把标志项交换到i的位置,然后把标志项的左右再进行递归操作
sortFun(arr, left, i - 1);
sortFun(arr, i + 1, right);
}

function exchange(arr, i, j) {
    let tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
 console.log(quicklySort([3,4,6,2,7,5]))

结果如下:

image.png

思路

快排的大致思路就是首先选定一个标志(上面代码是选了数组的最后一项当做标志项,也可以选择第一项,甚至任何项都可以),在定义左右两个指针(用于比较和交换值),然后以这个标志来把整个数组划分为两部分(一部分是大于标志项的,一部分是小于标志项的),然后拿标志项左右两部分分别进行递归操作。直到左右指针直到同一项位置,最终得到的结果就是排序后的结果,由于在整个的排序过程中都没有用到新的数组,所以它的空间复杂度非常小。

总结

只所以叫它为快排是因为在特定情况下它的运行速度比二分和冒泡快很多,但它的缺点就是不稳点,如果已知一个数组的结构可根据结构的不同来选取最合适的排序方式。