js快速排序算法

一、基本思想

是任取待排序序列的一个元素作为中心元素(可以用第一个,最后一个,也可以是中间任何一个),习惯将其称为pivot枢轴元素;

将所有比枢轴元素小的放在其左边;

将所有比它大的放在其右边;

形成左右两个子表;

然后对左右两个子表再按照前面的算法进行排序,直到每个子表的元素只剩下一个。

快速排序用到了分而治之的思想。将一个数组分成两个数组的方法为:

先从数组右边找到一个比枢轴元素小的元素,将数组的第一个位置赋值为该元素;

再从数组的左边找到一个比枢轴元素大的元素,将从上面取元素的位置赋值为该值;

依次进行,直到左右相遇,把枢轴元素赋值到相遇位置。

二、示例

输入数组
arr 为 [39 , 28 , 55 , 87 , 66 , 3 ,17 ,39*]
为了区别两个相同元素,将最后一个加上 * ;初始状态如下图:

 

定义一枢轴元素pivot,初始化为第一个元素的值,即39;
查询左边的元素的变量为left,初始值为第一个元素的索引0;
查询右边的元素的变量为right,初始值为第一个元素的索引7。
如下图:

 

 

 

第一轮排序过程从右边开始,从右边找到一个比枢轴元素小的,如果没找到right一直自减1;

 

然后把当前left所在元素赋值为该值;

这里right所指元素并没有空,只是为了好演示,设置为空(下同)

然后从左边开始找一个比枢轴元素pivot大的元素;如果没找到left一直自增1;

 

 

将当前right所指元素设为该值;

 

然后从右边找到一个比枢轴元素小的,如果没找到right一直自减1;

 

将当前left所指元素设为该值;

 

然后从左边开始找一个比枢轴元素pivot大的元素;如果没找到left一直自增1;

 

将当前right所指元素设为该值;

 

然后从右边找到一个比枢轴元素小的,如果没找到right一直自减1;

 

这时left和right相遇了,将枢轴元素赋值给当前位置

然后将数组分成了

 

[17,28,3] 与 [66, 87, 55, 39*]两部分;

再对这两部分进行上述环节即可。

反反复复,直到只剩下一个元素。

排序全过程

 

三、JavaScript代码实现

ar arr = [39 , 28 , 55 , 87 , 66 , 3 ,17 ,39];
console.log("排序前的数组:",arr)
/*
  对每一个数组进行分化的代码如下:
      初始化pivot为数组第一个元素;
      只要left还小于right就进行循环;
    外层循环内部如下:
      先从右边找一个比枢轴元素小的元素;
      将当前left所指元素赋值为找到的元素;
      再从左边找一个比枢轴元素大的元素;
      将当前right所指元素赋值为找到的元素;
      当left和right相等将枢轴元素赋值在此。
      最后返回中间元素的索引。
*/
function partition(arr,left,right){
    var pivot = arr[left];
    while(left<right){
        while(left<right && arr[right]>=pivot){
            right--;
        }
        arr[left] = arr[right];
        while(left<right && arr[left]<=pivot){
            left++;
        }
        arr[right] = arr[left];
    }
    arr[left] = pivot;
    return left;
}
/*
 排序:传数组,left为第一个元素索引0;right为最后一个元素索引数组长度减去1;
   定义一个将来划分为两个数组的中间元素的索引middle;
   如果left比right小,进行一次划分,将返回来的值赋值给middle;
   对left到middle - 1的部分进行一次快排(递归进行);
   对middle + 1到right的部分进行一次快排(递归进行)。
*/
function quickSort(arr,left,right){
    var middle;
    if(left<right){
        middle = partition(arr,left,right);
        quickSort(arr,left,middle-1);
        quickSort(arr,middle+1,right);
    }
}

quickSort(arr,0,arr.length-1);
console.log("排序后的数组:",arr)

四、时间复杂度

 1、理想的情况:

每次划分将待排序序列分成两个等长的子序列,则时间复杂度为O(nlog2n)

  2、最坏情况:

      每次所选的中间数是当前序列中的最值元素,这时每次划分的两个子表一个长度是0,一个是当前数组长度减去1。这样的话,长度为n的数组需要经过n趟划分,这是快速排序就蜕化为冒泡排序的过程,其时间复杂度为O(n2);

五、稳定性

如下面的数组

相同元素用 * 标出

[ 2 , 3 , 1, 1* ]

第一次排序为

[1* , 1, 2, 3]

相对顺序发生了变化,所以是不稳定的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值