排序之快速排序

79 阅读3分钟

为何要写这个?

说实话我的算法太弱了,算法弱跟你对api不熟悉一样,直接影响你的代码书写能力。而且,这个东西我可能今天看见别人写会了,下次真要自己写的时候又不会了,所以这几天我一直在写这个,只是好多次都没有结果(写着写着发现排序实现不了,然后想着想着哪里都不对,没天赋就得这样,花费比别人更多的时间)

简单描述一下快速排序

原则就是在数组中选定一个参照点,并以此为标准,实现大的占右边,小的占左边。 本来想画图说明的,因为这个更形象,后来想想,其实视屏讲解更快,所以有兴趣的朋友可以先看视屏讲解快速排序原理图再来看我这篇文章,也许你会觉得,真的值得一看!

根据上述原理我们先来快速实现一下

   function quickSort1(arr) {
    if (arr === null || arr.length === 0) {
        return []
    }
    let left = [],//左边的数组
        right = [], // 右边的数组
        leader = arr[0];//参照点
    for (let i = 1; i < arr.length; i++) {
        const item = arr[i]//下面多次用到,直接保存一下,有利于增加执行速度(小细节)
        item >= leader ? right.push(item) : left.push(item)
    }
    left = quickSort1(left);//递归排序左边
    right = quickSort1(right);//递归排序右边
    left.push(leader);//加上参照物
    return [...left, ...right]
}

let arr = [1, 2, 566, 33, 33, 6, 63, 66, 59, 945, 66, 463, 66, 552]

console.log(quickSort1(arr))//[1, 2, 6, 33, 33, 59,63, 66, 66, 66, 463, 552,566, 945]

这种快速排序应该是大家最好理解的那种了吧,至少我不会写第二种的时候第一种看一遍就会写。这里一直有个感想,以前学不会一样东西一直觉得是自己脑子太笨,后来意识到可能是方法不对,包括我再实现接下来第二种方法的时候,说实话我思考了两天,原理一看就会,代码一写就废,而且经常写着写着就像睡觉,今天也没觉得能写出来,只是忙了一天,然后洗了个澡,静下心来一步一步写了起来,我真的是写一步运行一次,而且没有看任何人的代码,就是自己怎么想怎么写,这样下次再写快速排序应该就很难忘记了吧。

    function quickSort(arr) {
        function _change(arr, a, b) {
            let temp = arr[a];
            arr[a] = arr[b];
            arr[b] = temp
        }
        //这里内部定义一个辅助方法
        function _quickSort(arr, start, end) {
            // 递归必须要有出口
            if (start >= end) {
                return
            }
             //这里我们需要两个指针分别是left,right,还有参照物leader
            let left = start + 1, right = end, leader = arr[start];
            while (left < right) {
                // 如果左边指针小于右边 并且左边指针对应的值小于参照物leader,那么left++
                while (left < right && arr[left] < leader) {
                    left++
                }
                //同理右边可得
                while (right > left && arr[right] >= leader) {
                    right--
                }
                //这里进行交换,无论哪种情况
                _change(arr, left, right)
                //这里第一次交换完毕,如果left<right,上述过程应该继续,于是有外层的while循环
            }
            //这里说明 left === right,于是比较left 这里的值跟参照物leader的值得大小,方便把参照点放在数组合适位置,实现左边的比参照点小,右边的大于等于参照点,一下以left为准,right也可
            if (arr[left] >= leader) {//如果大于等于参照物,那么left往左移动一格,否则直接交换
                left--;
            }
            _change(arr, start, left)
            //这里对左边进行排序
            _quickSort(arr, start, left - 1);
            //这里对右边进行排序
            _quickSort(arr, left + 1, end);

        }
        _quickSort(arr, 0, arr.length - 1)
}
let arr = [235, 23, 56, 233, 6, 3, 63, 36]
quickSort(arr)
console.log(arr)//[3,6,23,36,56,63,233,235]