快速排序是一种常用的排序算法,快速排序也使用了分而治之(divide /dɪˈvaɪd/ and conquer /ˈkɒŋkər/ 简称D&C)。分而治之是一种思路,它是一种递归思想,每个递归函数都有两部分:

  1. 基线条件(base case)
  2. 递归条件(recursive case) /rɪˈkɜːsɪv/

递归条件指的是函数调用自己,而基线条件则指的是函数不再调用自己,从而避免形成无限循环。

function fibonacci(n) {if (n <=2) {  // n <=2 基线条件return 1};return fibonacci(n - 2) + fibonacci(n - 1);  // n>2 为递归条件
};
fibonacci(10)  //55

有了递归的基础接下来我们再来看下快速排序的写法!

1.快速排序易懂版

有下图这么一个数组[4, 5, 1, 6, 9, 22, 6]

我们先确定基准点,那么我们取中间值为基准点!

然后以基准点为参照值对数组进行排序,比6小的放左边,比6大的放右边!

第一轮排序完成了,我们开始对左右两边再进行排序,先看左边的!

和上面一样,先取中间值为基准点!

然后以基准点为参照值对数组进行排序,比5小的放左边,比5大的放右边,这里4,1都比5小,所以都在左边,右边没有值!

接下来对1,4这两个元素进行排序,先取基准点!


以基准点为参照值对数组进行排序,比4小的放左边,比4大的放右边,右边也没有值!

再看右边的数组!

先取中间值为基准点!

然后以基准点为参照值对数组进行排序,比22小的放左边,比22大的放右边,这里9,6都比22小,所以都在左边,右边也没有值!


接下来对6,9这两个元素进行排序,先取基准点!

以基准点为参照值对数组进行排序,比9小的放左边,比9大的放右边,右边也没有值!

最终合并数组完成整个排序(因为数字比较少,我把所有的步骤都列出来了)!

上面是快速排序的一个完整的步骤!那么我们代码中怎么实现!

  1. 明确基线条件和递归条件(当数组的元素为空或者只包含一个元素,在这种情况下,只需原样返回数组,根本就不用排序,那么当数组的元素大于1时就是递归条件)。
  2. 选择好基准点为parseInt(arr.length / 2)。
  3. 创建左边一个数组left,右边一个数组为right,当比基准点大时放进right里面,比基准点小时放进left里面。
  4. 然后对left,right 不断的重复2,3步骤。
  5. 合并数组。
function quickSort(arr) {let temp = arr.slice(0), //复制一个数组left = [],right = [],middle = temp[parseInt(temp.length / 2)]; //取基准点if (temp.length < 2) {//递归的基线条件return temp;};temp.splice(parseInt(temp.length / 2), 1); //数组去掉基准点这个元素for (var i = 0; i < temp.length; i++) {if (temp[i] < middle) {left.push(temp[i]) //比基准点小时放进left里面} else {right.push(temp[i])//比基准点大时放进right里面};};return quickSort(left).concat([middle]).concat(quickSort(right));//递归并合并数组
};
console.log(quickSort([4, 5, 1, 6, 9, 22, 6])); //[1, 2, 5, 6, 6, 9, 22]

上面这种快速排序比较易懂,但是每次都要创建left,right数组,这样就增加了空间复杂度!效率就降低了!

2.快速排序易变种版

我们还是要先找基准点,那么这里的基准点就选第一个元素,上面我们是创建left,right数组来区分,这里可以用两个变量i和j,分别指向序列最左边和最右边,你可以理解i是小于基准点的值,j是大于基准点的值,还是用上面的数组[4, 5, 1, 6, 9, 22, 6]

这里基准点是4,首先,变量j向左移动,当小于基准点4时停下脚步!,然后变量i向右移动,当大于基准点4时候停下脚步!

这里变量i的值是5,变量j的值是1,交换I,j的值!

然后j再向左移动找比基准点4小的值,找到了1停下脚步,接着i向右移动找比基准点4大的值,当碰到了j停下脚步!

最后交换基准点和i或者j的值(它们相等)

第一轮排序就完成了,4左边是比4小的,4右边是比4大的,左边右边进行重复上面的操作!

那么我们代码中怎么实现!

  1. 明确基线条件和递归条件(如果数组只有一个元素,根本就不用排序,那么当数组的元素大于1时就是递归条件)。
  2. 选择好基准点为arr[0]。
  3. 创建两个变量i和j,分别指向序列最左边和最右边。
  4. 不断的重复2,3步骤。
  let arr = [4, 5, 1, 6, 9, 22, 6];function quickSort(arr, left, right) {let i = left,j = right,middle = arr[left];//取基准点if (left >= right) {//如果数组为空或者只有一个元素,跳出递归return;};while (i < j) {//当i=j跳出循环while (arr[j] > middle && i < j) {//从右向左找第一个比基准点小的值j--;};while (arr[i] <= middle && i < j) {//从左向右找第一个大于等于基准点的值,注意这里可以相等,是为了保证基准点的位置不变i++;};if (i < j) {//交换值let temp = arr[i];arr[i] = arr[j];arr[j] = temp;}};当i和j相等,再和基准值交换值arr[left] = arr[i];arr[j] = middle;quickSort(arr, left, i - 1);//递归基准点左边的数组,并且当left>=i-1跳出递归quickSort(arr, i + 1, right);//递归基准点右边的数组,并且当i+1>=right跳出递归};quickSort(arr, 0, arr.length - 1);//[1, 4, 5, 6, 6, 9, 22]

以上两种方法都可以实现快速排序,只不过是实现的方式不一样而已,快速排序的平均运行时间为O(n log n),最糟情运行时间为 O(n2),不懂的话可以点击算法的时间复杂度(大O表示法)

快速排序原理和实现(图文讲解)相关推荐

  1. C++动态内存管理好难怎么办?零基础图文讲解,小白轻松理解原理

    首先我们先了解一下内存: C语言使用malloc/free动态管理内存空间,C++引入了new/delete,new[]/delete[]来动态管理内存. 如果大家在自学C++中遇到困难,想找一个学习 ...

  2. 面试挂在JVM?别慌,图文讲解JVM工作原理,看完还不懂我跪键盘

    本文转载自:面试挂在JVM?别慌,图文讲解JVM工作原理,看完还不懂我跪键盘 JDK,JRE,JVM的联系是啥? JVM Java Virtual Machine JDK Java Developme ...

  3. matlab电动机星三角启动仿真,电机星三角启动注意事项图文讲解

    原标题:电机星三角启动注意事项图文讲解 交流异步电动机启动电流可达到额定电流的5-8倍,为避免大电流对电机线圈和电网的冲击,对于一些功率较高的电机必须使用降压启动,星-三角启动就是一种最为常见且简单的 ...

  4. hs控什么意思_图文讲解传统双控、多控如何升级为米家智能家居的无限控

    小白中完全不懂电路,然后智能家居就更不懂的占比还挺多,问的问题怎么说呢,你还不知道该怎么三言两语回答他,好吧,写一篇如何把家里双控线路改造为智能家居无限控的详细讲解文章,为大家彻底解惑^_^ 如果想要 ...

  5. Java实现快排(图文讲解)

    文章目录 Java实现快速排序 快速排序原理 快速排序一次划分图文演示过程 整个快速排序的过程 具体Java代码实现 简结快速排序的性能 Java实现快速排序 冲鸭,装上涡轮增鸭,开始学习快速排序算法 ...

  6. 刷机前对LG Nexus 5进行双清的方法(图文讲解)

    今天小编为大家整理分享一下刷机前对LG Nexus 5进行双清的方法(图文讲解),大家在为LG Nexus 5刷机的时候,刷入LG Nexus 5 ROM...  今天小编为大家整理分享一下刷机前对L ...

  7. 彻底搞透视觉三维重建:原理剖析、代码讲解、及优化改进

    视觉三维重建 = 定位定姿 + 稠密重建 + surface reconstruction +纹理贴图.三维重建技术是计算机视觉的重要技术之一,基于视觉的三维重建技术通过深度数据获取.预处理.点云配准 ...

  8. 新概念一册电子书课本_新概念英语第二册完整版:音频+动画视频+课本图文讲解...

    新概念英语 <新概念英语>是一经典得已经无需多做解释的英语学习好教材.它采用和人们生活.学习密切相关的语言材料,遵循语言习得的科学性及渐进性,可全面提升学生的听.说.读.写能力,使语言能力 ...

  9. pppoe 服务器 无线,无线路由器怎么设置PPPOE拨号【图文讲解】

    1.如果是电话线到家,首先把路由器的WAN口和Modem的LAN口连接起来,电脑网卡连接路由器任意一个LAN口;如果是网线到家,就直接把网线接到路由器WAN口. 然后为电脑设置网络参数,指定IP地址, ...

  10. linux内存管理详解,Linux内存管理图文讲解.pdf

    Linux内存管理图文讲解 逻辑地址.线性地址.物理地址和虚拟地址 一.概念 物理地址(physical address) 用于内存芯片级的单元寻址,和处理器和 CPU 连接的地址总线相对应. 这个概 ...

最新文章

  1. h5仿微信聊天(高仿版)、微信聊天表情|对话框|编辑器
  2. 趣谈网络协议笔记-零
  3. 搜狗拼音输入法新加词库的基本使用
  4. 统一沟通-技巧-12-Lync-CX600-3000-5000-配置-internet
  5. RecyclerView因版本问题无法加载
  6. java oracle database user dsn_跨会话序列化数据库连接
  7. 计算机学3d建模吗,计算机三维建模与动画基础
  8. 来了!索尼官宣PS5游戏主机:比预计的时间稍晚一些
  9. 年轻人必须在北上广工作吗
  10. 微信小程序用户拒绝授权之后重新调用
  11. ACPI文件处理与屏蔽独显、亮度调节
  12. 【存储测试】vdbench存储性能测试工具
  13. camera link心得
  14. 标贝科技|AI企业级应用榜单发布,百度、讯飞、标贝科技等50家产品上榜
  15. Sort Sort Sort
  16. keep跑步数据修改器_一只手环就能指导运动?Keep 想做你手腕上的魔鬼教练
  17. Security+认证实用问题手册
  18. 数据仓库中的数据粒度
  19. 【Usaco 2009 Feb】Bullcow 牡牛和牝牛
  20. Linux 虚拟内存和物理内存的理解(转)

热门文章

  1. C++ [STL容器反向迭代器]
  2. 养猫日记2022120
  3. 商场展览展会演出发布会活动邀请媒体,媒体邀约需要注意什么
  4. 27-字符串加密和解密算法
  5. 《Linux内核分析与实现》 第四周 读书笔记
  6. linux后台启动,不输出日志文件
  7. MySQL-定时任务
  8. js tree树形结构,通过子节点找到所有父节点
  9. 44 R关联分析——Apriori算法
  10. imagecopymerge