数据结构与算法——排序3(快速排序)

一、🐶 快速排序的原理

  • 分区: 从数组中任意选择一个基准,所有比基准小的元素放到基准前面,比基准大的元素放到基准的后面
  • 递归:递归地对基准前后的子数组进行分区

快排实现方式一代码如下(不考虑空间消耗):

js 复制代码
Array.prototype.quickSort = function () { 
    const rec = (arr) => { 
       // 预防数组是空的或者只有一个元素, 当所有元素都大于等于基准值就会产生空的数组
       if(arr.length === 1 || arr.length === 0) { return arr; }
       const left = [];
       const right = [];
       //以第一个元素作为基准值   
       const mid = arr[0];
       //小于基准值的放左边,大于基准值的放右边
       for(let i = 1; i < arr.length; ++i) { 
           if(arr[i] < mid) { 
               left.push(arr[i]);
           } else { 
               right.push(arr[i]);
           }
       }
        //递归调用,最后放回数组    
       return [...rec(left),mid,...rec(right)];
    };
    const res = rec(this);
    res.forEach((n,i) => { this[i] = n; })
}

const arr = [2,3,4,5,3,1];
arr.quickSort();
console.log(arr);

总结:简明易懂,好理解,好写,适合面试的时候手撸代码。

时间复杂度
  • 最好时间复杂度为O(nlog₂n)
  • 最坏时间复杂度为O(n²)
  • 平均时间复杂度为O(nlog₂n)
空间复杂度

需要额外的left和right临时空间所以空间复杂度为O(nlog₂n)

稳定性

代码第8行约定以第一个元素作为基准值,代码11-15行约定,当数据等于mid的时候放到right区间,所以相同元素位置前后不会改变。属于稳定的排序算法

快排实现方式二代码如下(不占用额外的空间消耗):

js 复制代码
function quickSort(arr, low, high) {
  if (low < high) {
    let pivotposition = partition(arr, low, high);
    quickSort(arr, low, pivotposition-1);
    quickSort(arr, pivotposition+1, high);
  }  
} 

function partition(arr, low, high) {
  let temp = arr[low];
  while(low < high) {
    // 此时左边位置为空,所以从右边去找,如果arr[high] >= temp移动指针接着往前找
    while(low < high && arr[high] >= temp){
      high--;
      continue;
    }
    // 此时左边位置为空,从右边去找,如果arr[high] < temp,则把它赋值给左边,此时右边的位置为空,跳出循环,重头再来
    while(low < high && arr[high] < temp){
      arr[low] = arr[high];
      low++;
      break;
    }
    // 此时右边为空,去左边找,找到arr[low] <= temp,移动指针接着往后找
    while(low < high && arr[low] <= temp){
      low++;
      continue;
    }
    // // 此时右边为空,去左边找,找到arr[low] > temp,把它赋值到右边,跳出循环,重头再来
    while(low < high && arr[low] > temp){
      arr[high] = arr[low];
      high--;
      break;
    }
  }
  arr[low] = temp;
  return low;
}
  • 我们遍历 p 到 r 之间的数据,将小于 pivot 的放到左边,将大于 pivot 的放到右边,将 pivot 放到中间。
  • 经过这一步骤之后,数组 p 到 r 之间的数据就被分成了三个部分,前面 p 到 q-1 之间都是小于 pivot 的,中间是 pivot,后面的 q+1 到 r 之间是大于 pivot 的。
  • 据分治、递归的处理思想,我们可以用递归排序下标从 p 到 q-1 之间的数据和下标从 q+1 到 r 之间的数据,直到区间缩小为 1,就说明所有的数据都有序了。
时间复杂度
  • 分区均衡,最好时间复杂度为O(nlog₂n)
  • 分区不均衡,最坏时间复杂度为O(n²)
  • 平均时间复杂度为O(nlog₂n)
空间复杂度

只需要一个temp空间,所以空间复杂度为O(1)

稳定性

涉及到左右位置的交换,所以排序过程中2个相同的数位置会交换,是不稳定的排序算法。

相关推荐
小刘|24 分钟前
《Java 实现希尔排序:原理剖析与代码详解》
java·算法·排序算法
jjyangyou29 分钟前
物联网核心安全系列——物联网安全需求
物联网·算法·安全·嵌入式·产品经理·硬件·产品设计
van叶~1 小时前
算法妙妙屋-------1.递归的深邃回响:二叉树的奇妙剪枝
c++·算法
简简单单做算法1 小时前
基于Retinex算法的图像去雾matlab仿真
算法·matlab·图像去雾·retinex
我要洋人死1 小时前
导航栏及下拉菜单的实现
前端·css·css3
云卓SKYDROID1 小时前
除草机器人算法以及技术详解!
算法·机器人·科普·高科技·云卓科技·算法技术
科技探秘人1 小时前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人1 小时前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR1 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香1 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel