快速排序原理和实现(图文讲解)
快速排序是一种常用的排序算法,快速排序也使用了分而治之(divide /dɪˈvaɪd/ and conquer /ˈkɒŋkər/ 简称D&C)。分而治之是一种思路,它是一种递归思想,每个递归函数都有两部分:
- 基线条件(base case)
- 递归条件(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时就是递归条件)。
- 选择好基准点为parseInt(arr.length / 2)。
- 创建左边一个数组left,右边一个数组为right,当比基准点大时放进right里面,比基准点小时放进left里面。
- 然后对left,right 不断的重复2,3步骤。
- 合并数组。
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时就是递归条件)。
- 选择好基准点为arr[0]。
- 创建两个变量i和j,分别指向序列最左边和最右边。
- 不断的重复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表示法)
快速排序原理和实现(图文讲解)相关推荐
- C++动态内存管理好难怎么办?零基础图文讲解,小白轻松理解原理
首先我们先了解一下内存: C语言使用malloc/free动态管理内存空间,C++引入了new/delete,new[]/delete[]来动态管理内存. 如果大家在自学C++中遇到困难,想找一个学习 ...
- 面试挂在JVM?别慌,图文讲解JVM工作原理,看完还不懂我跪键盘
本文转载自:面试挂在JVM?别慌,图文讲解JVM工作原理,看完还不懂我跪键盘 JDK,JRE,JVM的联系是啥? JVM Java Virtual Machine JDK Java Developme ...
- matlab电动机星三角启动仿真,电机星三角启动注意事项图文讲解
原标题:电机星三角启动注意事项图文讲解 交流异步电动机启动电流可达到额定电流的5-8倍,为避免大电流对电机线圈和电网的冲击,对于一些功率较高的电机必须使用降压启动,星-三角启动就是一种最为常见且简单的 ...
- hs控什么意思_图文讲解传统双控、多控如何升级为米家智能家居的无限控
小白中完全不懂电路,然后智能家居就更不懂的占比还挺多,问的问题怎么说呢,你还不知道该怎么三言两语回答他,好吧,写一篇如何把家里双控线路改造为智能家居无限控的详细讲解文章,为大家彻底解惑^_^ 如果想要 ...
- Java实现快排(图文讲解)
文章目录 Java实现快速排序 快速排序原理 快速排序一次划分图文演示过程 整个快速排序的过程 具体Java代码实现 简结快速排序的性能 Java实现快速排序 冲鸭,装上涡轮增鸭,开始学习快速排序算法 ...
- 刷机前对LG Nexus 5进行双清的方法(图文讲解)
今天小编为大家整理分享一下刷机前对LG Nexus 5进行双清的方法(图文讲解),大家在为LG Nexus 5刷机的时候,刷入LG Nexus 5 ROM... 今天小编为大家整理分享一下刷机前对L ...
- 彻底搞透视觉三维重建:原理剖析、代码讲解、及优化改进
视觉三维重建 = 定位定姿 + 稠密重建 + surface reconstruction +纹理贴图.三维重建技术是计算机视觉的重要技术之一,基于视觉的三维重建技术通过深度数据获取.预处理.点云配准 ...
- 新概念一册电子书课本_新概念英语第二册完整版:音频+动画视频+课本图文讲解...
新概念英语 <新概念英语>是一经典得已经无需多做解释的英语学习好教材.它采用和人们生活.学习密切相关的语言材料,遵循语言习得的科学性及渐进性,可全面提升学生的听.说.读.写能力,使语言能力 ...
- pppoe 服务器 无线,无线路由器怎么设置PPPOE拨号【图文讲解】
1.如果是电话线到家,首先把路由器的WAN口和Modem的LAN口连接起来,电脑网卡连接路由器任意一个LAN口;如果是网线到家,就直接把网线接到路由器WAN口. 然后为电脑设置网络参数,指定IP地址, ...
- linux内存管理详解,Linux内存管理图文讲解.pdf
Linux内存管理图文讲解 逻辑地址.线性地址.物理地址和虚拟地址 一.概念 物理地址(physical address) 用于内存芯片级的单元寻址,和处理器和 CPU 连接的地址总线相对应. 这个概 ...
最新文章
- h5仿微信聊天(高仿版)、微信聊天表情|对话框|编辑器
- 趣谈网络协议笔记-零
- 搜狗拼音输入法新加词库的基本使用
- 统一沟通-技巧-12-Lync-CX600-3000-5000-配置-internet
- RecyclerView因版本问题无法加载
- java oracle database user dsn_跨会话序列化数据库连接
- 计算机学3d建模吗,计算机三维建模与动画基础
- 来了!索尼官宣PS5游戏主机:比预计的时间稍晚一些
- 年轻人必须在北上广工作吗
- 微信小程序用户拒绝授权之后重新调用
- ACPI文件处理与屏蔽独显、亮度调节
- 【存储测试】vdbench存储性能测试工具
- camera link心得
- 标贝科技|AI企业级应用榜单发布,百度、讯飞、标贝科技等50家产品上榜
- Sort Sort Sort
- keep跑步数据修改器_一只手环就能指导运动?Keep 想做你手腕上的魔鬼教练
- Security+认证实用问题手册
- 数据仓库中的数据粒度
- 【Usaco 2009 Feb】Bullcow 牡牛和牝牛
- Linux 虚拟内存和物理内存的理解(转)