JavaScript算法入门-----快排以及其优化双路快排、三路快排

1、前言

之前刚刚开始向前端进发的时候,觉得算法对于前端来说并不是重点(这也是我开始学习前端的主要原因之一)。然鹅,现实的手还是狠狠的在我脸上亲吻了一下:(,相信大家都知道,这并不是一个愉快的过程。兜兜转转之后,终究还是躲不过去,就慢慢开始接触算法。 

首先开始接触的,也是面试的时候经常会被问到的就是相对比较“基础”的排序算法。其中一个排序算法总是被面试官宠幸,都希望面试官能够雨露均沾,可面试官不行啊,就问它,就问它。今天,我就来给大家讲解一下这个总被面试官宠幸的排序算法-----快排

2、单路快排

面试官:请在纸上实现快排的实现过程。(其实他可能是想去上厕所了)

首先,先来介绍一下快排的思路。简单来说,就是对数组的每一项都执行以下操作:将小于(大于)此项的放在左边,将大于(小于)此项的放在右边,完了。(大家是不是心里正在MMP),不要急,听我慢慢道来:

我们假设有一个数组:

const arr = [5, 10, 32, 6, 1, 7, 8, 2, 20, 9]

接下来,嘿嘿嘿嘿,我们就要对这个数组酱酱酱了。

在对数组处理之前,我们想要先找到一个基准值,一般来说,取当前操作的数组段的第一项,大家如果不清楚我说的当前操作的数组段是什么意思,往后看。

function fastSort(arr, start, end) {
    const base = arr[statr]; // 将arr第一项作为base值
    let flag = start; // base值的索引
    for( let i = start + 1; i <= end; i++ ) {
        if (arr[i] < base) {
            arr.splice(flag, 0, arr.splice(i, 1)[0]);
            flag += 1
        } // 将小于base的数据放在base的左边,将大于的值留在右边
    }
}

        这个函数执行一次之后,结果是这样子的:

[1, 2, 5, 10, 32, 6, 7, 8, 20, 9]

        非常明显,第一次执行我们取的base值为数组的第一项5,执行完成后,5左边的都是小于5的,5右边的都是大于5的,然后,我们只需要对左右两个数组段进行相同的操作,

fastSort(arr, start, flag - 1); // 对base值左边的数据进行相同的操作
fastSort(arr, flag + 1, end); // 对base值右边的数据进行相同的操作

        就这样,我们以此递归下去,直到我们的方法取到的start不小于end的时候,结束方法的执行。(切记,一定要加上结束条件,否则,方法会一直执行下去。)

        最后的结果就是,对于数组的每一项,左边的都是小于这一项,右边的都大于这一项,此时,排序已经完成。

        完整的代码:

/**
 * 单路快速排序
 * @param arr 要排序的数组
 * @param start 当前执行数组段的开始的索引
 * @param end 当前执行数组段的结束的索引
 * @returns {boolean}
 */
function fastSort(arr, start = 0, end = arr.length - 1) {
    // 终止条件,如果没有,方法的执行就不会停止
    if (start >= end) return false;
    const base = arr[start]; // 将arr第一项作为base值
    let flag = start; // base值的索引
    for (let i = start + 1; i <= end; i++) {
        if (arr[i] < base) {
            arr.splice(flag, 0, arr.splice(i, 1)[0]);
            flag += 1
        } // 将小于base的数据放在base的左边,将大于的值留在右边
    }
    fastSort(arr, start, flag - 1); // 对base值左边的数据进行相同的操作
    fastSort(arr, flag + 1, end); // 对base值右边的数据进行相同的操作
}

3、双路快排(待更新)

        这里介绍单路快排的一种优化:双路快排。

        大家看过上面单路快排的代码,都能看到,在单路快排中,只有一个游标,从数组的start位置依次移动到end位置,在移动过程中,将小于base的值放到左边,将大于base的值放在右边,然后递归实现整个数组的排序。而在双路快排中,则是有两个游标,分别在数组的start位置(游标A)和end位置(游标B),游标A从start开始向右寻找大于base(仍然取第一项)的值,游标B从end开始想做寻找小于等于base的值,然后将两个值进行位置互换,然后接着寻找,知道两个游标相遇,将相遇位置的值和base值进行位置互换。这样一次寻找过程结束,接下来对于左右两段进行重复的操作,直至整个数组排序完成。

function fastSort(arr, start = 0, end = arr.length - 1) {
    // 终止条件
    if (start >= end) return false;
    let left = start, right = end, base = arr[start];
    while (left < right) {
        // 从右向左,寻找第一个小于base的值
        while (arr[right] > base && right >= left) right --;
        // 从左向右,寻找第一个大于base的值
        while (arr[left] <= base && left < right) left ++;
        // 将两个值交换位置
        [arr[left], arr[right]] = [arr[right], arr[left]];
    }
    // 将最后两个游标相遇的位置的值与base值交换
    [arr[start], arr[left]] = [arr[left], arr[start]];
    fastSort(arr, start, left - 1);
    fastSort(arr, right + 1, end)
}

4、三路快排(待更新)

       

        以上只是我的一点学习总结,如果有错误的地方,请指出来,我会改正,大家互相学习,才会进步的更快。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值