javascript 实现快排 ,三向切分快排

比如说对数组快排的思路就是:

  1. 选取一个基准(可以选数组的开头最为基准,令 i = 0 ;j = array.length -1)
  2. 从arr[j]向前遍历(j--),当该值大于基准,则交换,退出循环(break)。
  3. 从arr[i]向后遍历(i++),当该值大于基准,则交换,退出循环(break)。
  4. 重复步骤2和步骤3,直到 i == j。此时a[i] 左边都小于a[i],右边都大于a[i]。
  5. 根据下标分别递归左右两边的部分,注意一下递归出口就ok了。
/**
 * @author vigdxx@gmail.com
 * @param {Array} arr 待排序数组
 */
function quickSort(arr) {
    /**
     * @description 对数组的一部分进行排序,快排的基准为取待排序部分首项
     * @param {Number} i  待排序部分开始位置
     * @param {Number} j 待排序部分结束位置
     */
    function sort(i,j) {
        if(i >= j) {return} // 递归出口 
        let start = i;
        let end = j;
        while(i < j) {
            for(;j>i;j--) {
                if(arr[i] > arr[j]) {
                    [arr[j],arr[i]] = [arr[i],arr[j]];
                    break;
                } 
            }
            // 这个地方用 ++i,可以少一次比较
            for(;i<j;++i) {
                if(arr[i] > arr[j]) {
                    [arr[j],arr[i]] = [arr[i],arr[j]];
                    break;
                } 
            }
        }
        // 此时 i == j , arr[i] 左边的小于等于 arr[i],右边的大于arr[i]
        sort(start,i-1);
        sort(i+1,end)
    }
    sort(0,arr.length - 1);
    return arr;
}
复制代码

快排的时间复杂度是 O(nlogn),是一种不稳定的排序算法。当出现 大量重复数据时 ,上述快排算法并不是一种最有解,他的改进型:三向切分快速排序是一种更高效的算法。其思想就是把一个数组分为三部分,一部分小于pivot,一部分等于pivot,还有一部分大于pivot。代码如下

function quickSort3way(arr) {
  function sort3way(low, high) {
    if(low >= high) {return}
    let lt = low;//小于pivot的元素交换点
    let gt = high;//大于pivot的元素交换点
    let i = low +1;
    let pivot = arr[low];
    while(i <= gt) {
      if (arr[i] < pivot) {
        [arr[i], arr[lt]] = [arr[lt], arr[i]];
        i++;
        lt++;
      } else if (arr[i] === pivot) {
        i++;
      } else if (arr[i] > pivot) {
        [arr[i], arr[gt]] = [arr[gt], arr[i]];
        gt--;
        //此时 不能i++,因为交换后不能保证 arr[i] 等于还是小于 pivot
      }
    }
    sort3way(low,lt-1);
    sort3way(gt+1,high);
  }
  sort3way(0,arr.length-1);
  return arr;
}
复制代码

转载于:https://juejin.im/post/5af69223f265da0b7b35fb7b

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值