JavaScript中的快速排序

1.快速排序有多重要?

快速排序几乎可以说是目前所有排序算法中,最快的一种排序算法。(当然,没有任何一种算法在任意情况下都是最优的。比如:希尔排序确实在某些情况下可能好于快速排序,但大多数情况下,快速排序还是比较好的选择~)

2.快速排序的思想:

先来回忆一下冒泡排序的思路:对于未排序的各元素依次比较相邻两个元素大小关系;

              如果左边的数大,则两元素交换位置,向右移动一个位置,比较下面两个元素;

              当走到最右端时,最大的元素一定被放在了最右边。

    按照这个思路,从最左端重新开始,第二轮走到倒数第二个位置即可.............

快速排序就是冒泡排序的升级版快速排序可以在一次循环中(其实是递归调用),找出某个元素的正确位置,并且该元素之后不需要任何移动。

快速排序最重要的思想:分而治之。

可以看到,以上是递归的处理左边的数据和右边的数据。那么问题来了?我该如何选择一个数字来进行划分呢?为什么选择65、31、81呢?接下来学习如何选择一个:枢纽

3.快排的实现思路(我直接写在纸上了,字不好看,但知识很有意思~)

可以看到枢纽起着至关重要的作用~~,接下来看看如何选择枢纽(尽量选择靠中间的)

这里我的做法是:选择头、中、尾三个数,然后比较大小,选择一个中位数

对应到上个例题中就是:left:0,   right:length-1;    center:(left+right)/2

           left:[0]    right:[8]      center:[4]

           left:23   right:72      center:76

中位数为:72,所以就将72定位枢纽(可能这里这个数据不太好,但原理就是这么个原理~)

接下来就将这三个数字排序之后放在对应的位置,将比枢纽小的放在第一个,比枢纽大的放在最后一个,将枢纽放在倒数第二位

4.代码实现:

 //  快速排序代码
    // 1.选择枢纽
    ArrayList.prototype.median = function (left, right) {
      // 取出中间的位置
      var center = Math.floor((left + right) / 2)
      // 对三个数据进行判断大小,并排序
      if (this.array[left] > this.array[center]) {
        // 如果左边的数大于中间的数,则两者交换
        this.swap(left, center)
      }
      if (this.array[center] > this.array[right]) {
        // 如果中间的数大于右边的数,则两者交换
        this.swap(center, right)
      }
      if (this.array[left] > this.array[right]) {
        // 如果中间的数大于右边的数,则两者交换
        this.swap(left, right)
      }
      // 将枢纽与倒数第二个位置上的数交换
      this.swap(center, right - 1)
      // 返回枢纽
      return this.array[right - 1]
    }
    ArrayList.prototype.quickSort = function(){
      this.quick(0,this.array.length-1)
    }
    //递归函数
    ArrayList.prototype.quick = function(left,right){
      // 结束条件:当传入的left比right大时(左边的数比右边的数大时)递归结束
      if(left >= right) return
      // 获取枢纽
      var pivot = this.median(left,right)
      // 左指针,变量,用于记录当前找到的位置
      var i = left
      // 右指针
      var j = right - 1
      // 开始进行交换
      while(true){
        // 左指针向右移,碰到比枢纽大的就停住(直接从++i开始,是因为left是比枢纽小的,不用再次比较)
        while(this.array[++i] < pivot ) {}
        // 右指针向左移,碰到比枢纽小的就停住
        while(this.array[--j] > pivot ) {}
        if(i<j){
          // 如果i<j,则i与j交换(比如例题中的第三步)
          this.swap(i,j)
        }else{
          // 当i>j的时候,退出循环
          break
        }
      }
      // i和枢纽交换,此时枢纽已经找到正确位置,枢纽左边的都是小于它的,枢纽右边的都是大于它的
      // (可以参考例题中的步骤4)
      this.swap(i,right-1)
      // 分而治之,枢纽左边的
      this.quick(left,i-1)
      // 分而治之,枢纽右边的
      this.quick(i+1,right)
    }

 

posted @ 2020-04-08 16:46  天空003  阅读(409)  评论(0编辑  收藏  举报