zoukankan      html  css  js  c++  java
  • 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)
        }
  • 相关阅读:
    XML(学习笔记)
    css样式学习笔记
    Request(对象)
    sql一些错误修改的总结
    转载(如何学习C#)
    sql server(学习笔记2 W3Cschool)
    sql sqrver(学习笔记1 W3Cschool)
    关于 flutter开发碰到的各种问题,有的已经解决有的一直没解决或者用其他方法替代
    关于 Flutter IOS build It appears that your application still contains the default signing identifier.
    关于 flutter本地化问题 The getter 'pasteButtonLabel' was called on null
  • 原文地址:https://www.cnblogs.com/yaya-003/p/12660051.html
Copyright © 2011-2022 走看看