快排之三路快排

快排的核心思想

排序数组中下标从 leftright 之间的一组数据,我们选择 leftright 之间的任意一个数据作为pivot(分区点),我们遍历 leftleft之间的数据,将小于priot的放到左边将大于pivot的放到右边,将pivot放到中间。经过这一步骤之后,数组 leftright 之间的数据就被分成了三个部分,前面 left 到 q-1 之间都是小于pivot,中间是pivot,后面 q+1 到 right 之间都是大于pivot

1. 大多数快排是这样写的,但是这样写有一个很大的问题是空间复杂度是O(n),当数据量很大的时候会耗费很大内存。
  function quickSort(arr) {
    if (arr.length < 2) {
      return arr;
    }
    let leftArr = [];
    let rightArr = [];
    // midNum 作为分区的点,必须从数组中提出来。
    // 因为是根据 midNum 进行分区的,首次会对 midNum 进行排序。
    let midNum = arr.splice(Math.floor(arr.length / 2), 1)[0];
    for (let i = 0; i < arr.length; i++) {
      if (arr[i] > midNum) {
        rightArr.push(arr[i]);
      } else {
        leftArr.push(arr[i]);
      }
    }
    return quickSort(leftArr).concat(midNum, quickSort(rightArr));
  }

2. 快排的正确写法

三路快排

function sortQuick(arr) {
    if (!arr || arr.length < 2) return arr;
    return sort(arr, 0, arr.length - 1);
  }
  function sort(arr, left, right) {
  	// 当 left 大于等于 right说明已经遍历一遍
    if (left >= right) return;
    // 数组排序
    let { less, great } = sortPartion(arr, left, right);
    // 对数组左边再次进行排序,不包括中间值,所以是0 - (less-1), (great+1) - right
    sort(arr, 0, less - 1);
    // 对数组右边再次进行排序
    sort(arr, great + 1, right);
    return arr;
  }
  // 此方法是把大的数放在右边,小的数放在左边
  function sortPartion(arr, left, right) {
    let less = left;
    let pivot = arr[right];
    let great = right;
    let start = left;
    while(start <= great) {
      if(arr[start] < pivot) {
        [arr[less], arr[start]] = [arr[start], arr[less]];
        start++;
        less++;
      } else  if(arr[start] > pivot) {
        [arr[start], arr[great]] = [arr[great], arr[start]];
        great--;
      } else {
        // arr[start] === pivot, 放在中间不动
        start++;
      }
    }
    return {
      less,
      great,
    };
  }
console.log(sortQuick([2, 4, 1, 5, 2, 3, 1, 34, 3, 5, 3, 1, 43]));
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值