js实现快速排序的两种方法

快速排序

快速排序是对冒泡排序的一种改进,它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

说白了就是从一个数组中找到一个数,把比他大的数都放在他的右边,把比他小的数都放在他的左边,然后在分别对左边和右边的数组做同样的事,就排好了。

在实际操作中,我们一般把“放到左边”和“放到右边”这种操作,通过交换位置来实现,以下是用js代码实现的快速排序:

const quickSort = (array) => {
 const sort = (arr, left = 0, right = arr.length - 1) => {
  if (left >= right) {//如果左边的索引大于等于右边的索引说明整理完毕
   return
  }
 let i = left
 let j = right
 const baseVal = arr[j] // 取无序数组最后一个数为基准值
 while (i < j) {//把所有比基准值小的数放在左边大的数放在右边
  while (i < j && arr[i] <= baseVal) { //找到一个比基准值大的数交换
   i++
  }
  arr[j] = arr[i] // 将较大的值放在右边如果没有比基准值大的数就是将自己赋值给自己(i 等于 j)
  while (j > i && arr[j] >= baseVal) { //找到一个比基准值小的数交换
   j--
 }
  arr[i] = arr[j] // 将较小的值放在左边如果没有找到比基准值小的数就是将自己赋值给自己(i 等于 j)
 }
 arr[j] = baseVal // 将基准值放至中央位置完成一次循环(这时候 j 等于 i )
 sort(arr, left, j-1) // 将左边的无序数组重复上面的操作
 sort(arr, j+1, right) // 将右边的无序数组重复上面的操作
 }
 const newArr = array.concat() // 为了保证这个函数是纯函数拷贝一次数组
 sort(newArr)
 return newArr
}

这种实现方法猛的一看,还真不是很好理解,并且代码也有一点小多,不过跟着注释看下来还是比较容易懂的,并且效率很高哦哦哦哦,时间复杂度为n(log n),可以说是完全不复杂= =

然而,在我第一次手写js快速排序代码时,(当时仅仅知道原理,想自己实现一下)我是照着百度百科的图片写的,如下

在这里插入图片描述

这个图片真的是肥肠好懂!我一看,这不就是左边和右边分别建一个容器,一个放比基准数小的数,一个放比基准数大的数么,基准数就取数组的第一个数,这也太简单了吧。。。 所以我写出来了如下的代码:

function quick(arr){
    if(arr.length<=1){
        return arr;
    }
    var left = [],
        right = [],
        k = arr.splice(0, 1)[0];
        for(var i = 0;i<arr.length;i++){
            if(arr[i]>k){
                right.push(arr[i]);
            }else{
                left.push(arr[i]);
            }
        }
        return quick(left).concat([k],quick(right));
}

好吧我知道快速排序应该叫quickSort,基准值应该叫pivot但这不是重点!

别的先不说,就先看看这代码量,是不是少的让人心旷神怡?
然后再来对照上面的图片,左边一个空数组,右边一个空数组,基准值取数组的第一个值,比完大小把数塞进对应的数组里就可以了,是不是炒!鸡!简!单!肥!肠!好!懂!
等到一切尘埃落定,我们只需要简单的把三个数组连在一起就好了,我真是个小天才?

然而事情并没有这么简单

勤奋好学的博主,在度娘上搜索了一下js实现快速排序,发现我那个看似简洁大方沁人心脾的算法,是大家的最常想到的 普 遍 算 法 。同时它还有很多的弊端,比如:

它需要Ω(n)的额外存储空间,跟归并排序一样不好。在生产环境中,需要额外的内存空间,影响性能。

而上面那个花里胡哨眼花缭乱的算法,才是真正根正苗红的快速排序。。。
在这里插入图片描述
我太难了,我上辈子一定是道算法题…

  • 12
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值