快速排序

133 阅读2分钟

快速排序

快速排序核心思想:分而治之

对于一组数据,我们随机取出一个枢纽值,将小于该值的放到左边,大于该值的放到右边。然后递归执行,最后即可完成排序。

在快速排序中,枢纽值是一个非常重要的值,这里我们采用取头,中,尾三个值得中位数作为枢纽值。

步骤:

  1. 对头,中,尾三个值进行排序,找到中位数作为枢纽值
  2. 将枢纽值放到right-1位置
  3. 定义 i=left, j=right-1,然后移动指针i和j,找到i对应值大于枢纽值的值,j对应值小于枢纽值的值,然后将两个值进行交换,循环进行。
  4. 当i大于j时,结束循环,将i的值与枢纽值进行交换,此时左边的值都小于枢纽值,右边的都大于枢纽值。
  5. 递归枢纽值左边的数值,递归枢纽值右边的数值,最后完成排序

inde.png

代码实现;

 //交换函数
 function swap(i, j, arr) {
   let temp = arr[i];
   arr[i] = arr[j];
   arr[j] = temp;
 }
 //去除left,center,right三个下标对应值得中位数,作为枢纽值
 function getPovit(left, right, arr) {
   //这里需要向下取整,例如:left=4 right=5  ,如果向上取整,
   //center=5,最后的center和right-1交换,会覆盖掉left值,会出错
   let center = Math.floor((left + right) / 2);
   //从小到大排序
   if (arr[left] > arr[center]) {
     swap(left, center, arr);
   }
   if (arr[center] > arr[right]) {
     swap(center, right, arr);
   }
   //由于上面两步完成了最后right值肯定是最大的,那么最后我们还需要判断,left和center值的大小
   if (arr[left] > arr[center]) {
     swap(left, center, arr);
   }
   //将center这个枢纽值放到right-1位置
   //原因:由于right肯定大于,放入right-1,只需对right-1之前的值进行判断和交换即可,避免枢纽值被移动
   swap(center, right - 1, arr);
   return arr[right - 1];
 }
 ​
 function quickSort(arr) {
   function recSort(left, right) {
     //递归结束条件
     if (left >= right) return;
     //基数
     let povit = getPovit(left, right, arr);
 ​
     let i = left;
 ​
     let j = right - 1;
     //将大于枢纽值得放入枢纽值右边,小于的放入枢纽值左边
     while (i < j) {
       //由于初始值i==left,left肯定小于枢纽值,因次要++i,而不是i++
       while (arr[++i] < povit) {}
       //由于初始值j==right-1,right-1等于枢纽值,因次要--j,而不是j--
       while (arr[--j] > povit) {}
       //交换找到的两个值
       if (i < j) {
         swap(i, j, arr);
       }
     }
 ​
     swap(i, right - 1, arr);
     //对左侧进行递归
     recSort(left, i - 1);
     //对有测进行递归
     recSort(i + 1, right);
   }
   //开始递归
   recSort(0, arr.length - 1);
   return arr;
 }