数据结构与算法——排序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个相同的数位置会交换,是不稳定的排序算法。

相关推荐
ZTLJQ几秒前
基于机器学习的三国时期诸葛亮北伐失败因素量化分析
人工智能·算法·机器学习
番茄比较犟2 分钟前
Combine知识点switchToLatest
前端
北京_宏哥3 分钟前
🔥《爆肝整理》保姆级系列教程-玩转Charles抓包神器教程(15)-Charles如何配置反向代理
前端·面试·charles
Process6 分钟前
前端图片技术深度解析:格式选择、渲染原理与性能优化
前端·面试·性能优化
大松鼠君7 分钟前
轿车3D展示
前端·webgl·three.js
却尘7 分钟前
URL参数传递的两种方式:查询参数与路径参数详解
前端
下辈子再也不写代码了9 分钟前
分片下载、断点续传与实时速度显示的实现方法
前端·后端·github
婷婷婷婷10 分钟前
AntV X6 常用方法
前端
LucianaiB19 分钟前
拿到Offer,租房怎么办?看我用高德MCP+腾讯云MCP,帮你分分钟搞定!
前端·后端·cursor
JohnFF23 分钟前
48. 旋转图像
数据结构·算法·leetcode