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

相关推荐
Eric.Lee202120 分钟前
数据集-目标检测系列- 螃蟹 检测数据集 crab >> DataBall
python·深度学习·算法·目标检测·计算机视觉·数据集·螃蟹检测
林辞忧30 分钟前
算法修炼之路之滑动窗口
算法
￴ㅤ￴￴ㅤ9527超级帅40 分钟前
LeetCode hot100---二叉树专题(C++语言)
c++·算法·leetcode
liuyang-neu41 分钟前
力扣 简单 110.平衡二叉树
java·算法·leetcode·深度优先
penguin_bark1 小时前
LCR 068. 搜索插入位置
算法·leetcode·职场和发展
_GR1 小时前
每日OJ题_牛客_牛牛冲钻五_模拟_C++_Java
java·数据结构·c++·算法·动态规划
zqx_71 小时前
随记 前端框架React的初步认识
前端·react.js·前端框架
ROBIN__dyc1 小时前
表达式
算法
无限大.1 小时前
c语言实例
c语言·数据结构·算法
六点半8881 小时前
【C++】速通涉及 “vector” 的经典OJ编程题
开发语言·c++·算法·青少年编程·推荐算法