排序算法之快速排序

2023-10-27

高快省的排序算法

有没有既不浪费空间又可以快一点的排序算法呢?那就是“快速排序”啦!光听这个名字是不是就觉得很高端呢。

假设我们现在对“6  1  2 7  9  3  4  5 10  8”这个10个数进行排序。首先在这个序列中随便找一个数作为基准数(不要被这个名词吓到了,就是一个用来参照的数,待会你就知道它用来做啥的了)。为了方便,就让第一个数6作为基准数吧。接下来,需要将这个序列中所有比基准数大的数放在6的右边,比基准数小的数放在6的左边,类似下面这种排列:

3  1  2 5  4  6  9 7  10  8

在初始状态下,数字6在序列的第1位。我们的目标是将6挪到序列中间的某个位置,假设这个位置是k。现在就需要寻找这个k,并且以第k位为分界点,左边的数都小于等于6,右边的数都大于等于6。想一想,你有办法可以做到这点吗?

排序算法显神威

方法其实很简单:分别从初始序列“6  1  2 7  9  3  4  5 10  8”两端开始“探测”。先从找一个小于6的数,再从找一个大于6的数,然后交换他们。这里可以用两个变量i和j,分别指向序列最左边和最右边。我们为这两个变量起个好听的名字“哨兵i”和“哨兵j”。刚开始的时候让哨兵i指向序列的最左边(即i=1),指向数字6。让哨兵j指向序列的最右边(即=10),指向数字。

094811yilrz1tkzkvlrriz.png

 

首先哨兵j开始出动。因为此处设置的基准数是最左边的数,所以需要让哨兵j先出动,这一点非常重要(请自己想一想为什么)。哨兵j一步一步地向左挪动(即j--),直到找到一个小于6的数停下来。接下来哨兵i再一步一步向右挪动(即i++),直到找到一个数大于6的数停下来。最后哨兵j停在了数字5面前,哨兵i停在了数字7面前。

095430axy0qkhxxkktkktk.png

 

095437kdandfxhbtokk2qh.png

 

现在交换哨兵i和哨兵j所指向的元素的值。交换之后的序列如下:

6  1  2  5  9 3  4  7  10  8

095448k1kevwlz41373e7k.png

 

095458ejza15wscjv7iw5c.png

 

到此,第一次交换结束。接下来开始哨兵j继续向左挪动(再友情提醒,每次必须是哨兵j先出发)。他发现了4(比基准数6要小,满足要求)之后停了下来。哨兵i也继续向右挪动的,他发现了9(比基准数6要大,满足要求)之后停了下来。此时再次进行交换,交换之后的序列如下:

6  1  2 5  4  3  9  7 10  8

第二次交换结束,“探测”继续。哨兵j继续向左挪动,他发现了3(比基准数6要小,满足要求)之后又停了下来。哨兵i继续向右移动,糟啦!此时哨兵i和哨兵j相遇了,哨兵i和哨兵j都走到3面前。说明此时“探测”结束。我们将基准数6和3进行交换。交换之后的序列如下:

3  1 2  5  4  6  9 7  10  8

095506uz7e1uuukcblhkxv.png

 

095514cag5fumuqqg5jnsw.png

 

095530e0jf6p0y6aaaw2ir.png

 

、到此第一轮“探测”真正结束。此时以基准数6为分界点,6左边的数都小于等于6,6右边的数都大于等于6。回顾一下刚才的过程,其实哨兵j的使命就是要找小于基准数的数,而哨兵i的使命就是要找大于基准数的数,直到i和j碰头为止。 
OK,解释完毕。现在基准数6已经归位,它正好处在序列的第6位。此时我们已经将原来的序列,以6为分界点拆分成了两个序列,左边的序列是“3  1 2  5  4”,右边的序列是“9  7  10  8”。接下来还需要分别处理这两个序列。因为6左边和右边的序列目前都还是很混乱的。不过不要紧,我们已经掌握了方法,接下来只要模拟刚才的方法分别处理6左边和右边的序列即可。现在先来处理6左边的序列现吧。

左边的序列是“3  1  2 5  4”。请将这个序列以3为基准数进行调整,使得3左边的数都小于等于3,3右边的数都大于等于3。好了开始动笔吧

如果你模拟的没有错,调整完毕之后的序列的顺序应该是:
2  1  3  5  4
OK,现在3已经归位。接下来需要处理3左边的序列“2 1”和右边的序列“5 4”。对序列“2 1”以2为基准数进行调整,处理完毕之后的序列为“1 2”,到此2已经归位。序列“1”只有一个数,也不需要进行任何处理。至此我们对序列“2 1”已全部处理完毕,得到序列是“1 2”。序列“5 4”的处理也仿照此方法,最后得到的序列如下:
1  2  3 4  5  6 9  7  10  8

对于序列“9  7  10  8”也模拟刚才的过程,直到不可拆分出新的子序列为止。最终将会得到这样的序列,如下

1  2  3 4  5  6  7  8 9  10

到此,排序完全结束。细心的同学可能已经发现,快速排序的每一轮处理其实就是将这一轮的基准数归位,直到所有的数都归位为止,排序就结束了。下面上个霸气的图来描述下整个算法的处理过程。

 

232129ogop8gk0r8y7l70k.png

 

这是为什么呢?

快速排序之所比较快,因为相比冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样每次只能在相邻的数之间进行交换,交换的距离就大的多了。因此总的比较和交换次数就少了,速度自然就提高了。当然在最坏的情况下,仍可能是相邻的两个数进行了交换。因此快速排序的最差时间复杂度和冒泡排序是一样的都是O(N2),它的平均时间复杂度为O(NlogN)。其实快速排序是基于一种叫做“二分”的思想。

$arr = array(6,1,2,7,9,3,4,5,10,8);

 

function quickSort($arr){
    $rearr = array();
    $len = count($arr);
    if($len > 0){
        $base = $arr[0];
        $arr_left = $arr_right = array();
        for($i=1; $i<$len; $i++){
            if($arr[$i] < $base){
                $arr_left[] = $arr[$i];
            }else{
                $arr_right[] = $arr[$i];
            }
        }
        $arr_left = quickSort($arr_left);
        $arr_right = quickSort($arr_right);
        $rearr = array_merge($arr_left, array($base), $arr_right);
    }
    return $rearr;
}
$arr = quickSort($arr);
echo implode(', ', $arr);
//print_r($arr);

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

排序算法之快速排序 的相关文章

  • 从移动版本切换到完整网站(桌面版本)

    我使用此代码将用户从桌面版本引导到我的移动网站
  • 从 varchar(100) 类型获取时间(HH:MM AM/PM)格式

    如何将字符串 RD OT 07 30 转换为时间 我只知道如何将 07 30 AM 转换为时间 下面的代码给了我一个空白数据 id strtoupper POST id query mysql query SELECT STR TO DAT
  • 数组匹配值过滤器 PHP [重复]

    这个问题在这里已经有答案了 我尝试在数组中搜索 但根本没有得到任何结果 假设我有一个包含一些值的数组 所以当我想搜索它们时 它总是返回 null 不知道为什么 假设这是我的数组 data Array 0 gt Array id gt 122
  • PHP函数:查找参数的变量名和函数调用行号

    我想做这样的事情来简化日志操作 知道我应该投入什么吗 1 and 2 function log var var line 1 var name 2 line filepath log date Y m d txt message line
  • 存储 PHP 数组的首选方法(json_encode 与序列化)

    我需要将多维关联数据数组存储在平面文件中以进行缓存 我偶尔可能会遇到需要将其转换为 JSON 以便在我的 Web 应用程序中使用的情况 但绝大多数时候我会直接在 PHP 中使用该数组 在此文本文件中将数组存储为 JSON 或 PHP 序列化
  • 使用 GD lib 过滤器标准化 CSS 过滤器

    我想让用户拖动范围滑块并通过实时预览 CSS 滤镜 调整图像的亮度和对比度 然后使用 GD 库保存调整 但是 我似乎无法从 CSS 过滤器和 GD lib 亮度和对比度过滤器获得相同的结果 我的 CSS 过滤器范围为 50 150 其中 1
  • DateTime::修改和夏令时切换

    Using 日期时间 修改 http php net manual en datetime modify php在 DST 边界上添加一个小时会导致它跳过一个小时 e g d new DateTime 2015 11 01 12 00 00
  • PHP 5.3 中可以使用 new 作为方法名称吗?

    我很嫉妒 Ruby 使用 new 作为方法 在 PHP 5 3 中是否可以使用命名空间来实现这一点 class Foo public function new echo Hello 如你看到的here http php net manual
  • 尝试通过比较不同的表从 SQL 查询输出正确的值

    我对 SQL 非常陌生 需要有关如何使用正确的查询完成此任务的帮助 我有 2 张桌子需要使用 表 TB1 有 id Name 1 bob 2 blow 3 joe 表 TB2 有 compid property 1 bob 2 blow 我
  • Laravel 转义 Blade 模板中的所有 HTML

    我正在 Laravel 中构建一个小型 CMS 并尝试显示内容 存储在数据库中 它显示 HTML 标签而不是执行它们 就像所有打印数据都有一个自动 html entity decode 一样
  • PHP将数据写入文件中间而不重写文件的最佳方法是什么

    我正在 php 1GB 中处理大型文本文件 我正在使用 file get contents file txt NULL NULL 100000000 100 要从文件中间获取数据 但如果我想将文件中的数据更改为与原始数据不同的更改 我将不得
  • 使用月份、年份、星期几和周数计算月份中的某一天

    如何在 PHP 中计算月份中的某一天 并给出月份 年份 星期几和周数 例如 如果我有 2013 年 9 月 星期几是星期五 周数是 2 那么我应该得到 6 2013 年 9 月 6 日是第二周的星期五 实现此目的的一种方法是使用相对格式 h
  • PHP实现的机票预订系统

    如何防止预订系统中的座位被重复预订 我正在用 PHP 和 MYSQL 制作一个航空旅行预订系统模型作为一个项目 我有一个小问题 仅在付款后 门票和座位详细信息才会永久存储在此处 座位号在付款前分配 假设人 1 预订了飞机上的座位 x 并支付
  • YouTube 数据 api 未按 viewCount 排序

    我正在尝试按 viewCount 从高到低排序 YouTube 频道视频 但结果并不是按最大观看次数排序 以下是我正在使用的 API https www googleapis com youtube v3 search key api ke
  • PHPMailer:如何将 Content-Type 设置为 multipart/alternative

    我正在使用 phpmailer 发送电子邮件 但消息的标题中带有 Content Type text html 我怎样才能将其更改为多部分 替代 它应该类似于 mail gt 我的配置是 mail new PHPMailer mail gt
  • MYSQL:SQL查询获取自增字段的值

    我有一张桌子 主键是id及其自动递增 现在 当我插入新记录时 我需要获取更新记录的 id 我怎样才能做到这一点 如果我使用查询 select max id from table name 执行后我可以获得id 但我能确定它是刚刚插入的记录的
  • proc_open() 失败并显示“权限被拒绝”

    我正在尝试使用proc open 执行程序并打印结果 但是 我不断收到 许可被拒绝 的消息 已将脚本和可执行文件的 chmod 设置为 0777 但无济于事 ini get safe mode 是假的 可能出什么问题了 我正在使用 Cent
  • 使用 Apache 允许 Glassfish 和 PHP 在同一服务器中协同工作

    是否可以建立从 Java 到 php 文件的桥梁 我有一个用 Java 编写的应用程序 我需要执行http piwik org http piwik org 这是用 PHP 编写的 在服务器中 我正在运行 PHP 但无法从浏览器访问 php
  • 在 PHP 中设置 HTTP 响应代码(在 Apache 下)

    给出以下两种在 PHP 中设置 HTTP 响应代码的方法 具体来说 在 Apache 下 方法一 http response code 404 方法二 header HTTP 1 0 404 Not Found 我的问题是 除了这个事实之外
  • 纯旧 PHP 对象 (POPO) 一词的确切含义是什么?

    我想了解一下波波 我搜索了 popo 发现它代表 Plain Old Php Object 但我不确定 Plain Old Php Object 的确切含义 我想知道什么是 popo 以及在哪里使用它 谢谢 普通旧 在此处插入语言 对象是一

随机推荐

  • 最近我在忙什么之【毕业设计大纲】

    毕业设计工作日志 误差校正仿真 理论部分 Stewart平台位姿误差分析与标定研究 仿真部分 基于Matlab的全局搜索 单通道控制算法设计 滑模论文 根据论文仿真 填入参数 获取具体的传递函数 改进滑模的论文 扰动及对照实验设计 稳定平台
  • Ubuntu下使用MySQL(C++,Cmake)

    安装需要使用的库 sudo apt get install libmysqlclient dev 头文件 usr include mysql mysql的头文件在这里 引入头文件 include mysql h 如果找不到就 include
  • python web.py+requests 视频接收与发送

    web py是python中一个相对容易上手的web服务器搭建工具 1 安装方式 web py可以直接通过pip install 的方式安装即可 即 pip install web py 2 服务器 2 1 完整程序 import web
  • 迷宫问题—回溯法

    文章目录 一 项目分析的一般步骤 二 迷宫问题的具体解决 1 需求分析 2 问题分析 2 1 问题分析 2 2 数据结构设计的分析 3 设计 流程图设计 代码设计 3 1流程图设计 3 2代码设计 4 代码测试 5 完成交付 一 项目分析的
  • Springboot+Mybatis,dao加上@Repository注解无法注入

    在springboot 中 给mapper的接口上加上 Repository 无法生成相应的bean 从而无法 Autowired 这是因为spring扫描注解时 自动过滤掉了接口和抽象类 这种情况下可以在启动的类前加 上 MapperSc
  • 如何在 Python 中创建元组字典

    本演练是关于在 Python 中创建元组字典的全部内容 此数据结构存储键值对 通过组合字典和元组 可以创建元组字典 好处是以结构化格式组织且可访问的数据 可以轻松表示每个键的多个值 例如学生成绩或联系信息 让我们看看它如何有效地存储和检索复
  • 抖音生活小妙招类短视频创作技巧分享,几个方面带你了解整个流程

    想做抖音 又不想真人出镜 该选择什么项目做呢 更多精彩干货请关注共众号 萤火宠 免费领取108个抖音小项目 我们的学员中有宝妈 有大学生 也有不少职场人员 他们大多数都非常普通 没有什么很强的职业技能 也没有什么丰富的专业知识 但是他们有人
  • 找实习、工作的一点浅见

    一 实习的必要性 为什么需要去实习 1 实习能帮助自己增进对于具体职场的认识 包括具体工作的职责 内容 工作氛围 是否有较大压力等等 2 通过一段时间的实习经历 能帮助自己作出未来是否能胜任类似的工作的判断 如果有留用 是否考虑留下 如果没
  • 阿里的iOS协程库 coobjc 源码解析(一)——元组和协程

    Coobjc中的元组 底层主要依赖NSPointerArray进行实现 因为NSPointerArray支持插入nil指针 能配合元组中有对象为nil的特性 比较引人入胜的设计 主要是co tuple 这个宏定义 co tuple COTu
  • 学习笔记:SpringCloud 微服务技术栈_实用篇②_黑马旅游案例

    若文章内容或图片失效 请留言反馈 部分素材来自网络 若不小心影响到您的利益 请联系博主删除 前言 学习视频链接 SpringCloud RabbitMQ Docker Redis 搜索 分布式 史上最全面的 SpringCloud 微服务技
  • CSS水平垂直居中

    1 利用定位 margin auto 2 flex布局 3 grid布局 一 利用position margin auto
  • 深入剖析 Python 函数参数传递机制及高级应用

    前言 在本篇文章中 笔者将带你深入探讨 Python 函数传参的进阶主题 通过阅读本篇文章 你可以深入了解 Python 函数传参的进阶主题 掌握更多高级的函数技巧 提升你的 Python 编程能力 前面分享了Python 函数传参基础篇
  • linux 安装Elasticsearchhe和kibana以及启动遇到的错误解决(已成功运行)

    linux安装es和kibana 参考博文 https blog csdn net han12398766 article details 88373869 启动报错1 Exception elasticsearch keystore 这个
  • ELK+Wazuh搭建笔记

    本文借鉴https www cnblogs com backlion p 10394369 html 在此谢谢大佬指明方向 本人又总结了wazuh界面上opencat Vulnerabilities的后台配置情况 以及agent版本升级情况
  • 页面刷新 Vuex 数据丢失

    用 Vuex 的时候发现一个问题 在页面刷新的时候 vuex 的 state 里面存储的数据会丢失 问题产生原因 因为 store 里的数据是保存在运行内存中的 当页面刷新时 页面会重新加载 vue 实例 store 里面的数据就会被重新赋
  • 子类覆盖父类方法时参数以及方法的访问权限问题

    一 子类覆盖父类可继承方法时子类同名方法的访问权限必须大等于父类 父类private不被子类继承 也无覆盖一说 报错 Fatal error Access level to Sun3 a must be protected as in cl
  • 高精度高精度乘法(C++)

    高精度加法以及高精度单精度乘法这里就不过多赘述了 今天咱们的主角是高精度高精度乘法 咱们先回顾一下竖式乘法 我们先不急着进位 先来看看 对应位置上的数字都是这么来的 对于不足位我们补充零后 不难发现 对应位置的最后答案 是由该位置起以后的全
  • Timing Borrow的理解

    在集成电路设计中 静态时序分析 Static Timing Analysis STA 是一种常用的验证方法 用于确保芯片在运行时的时序约束得到满足 在STA分析过程中 Timing Borrow是一种时序收敛技术 即在某些情况下 可以借用下
  • PowerMock--Mock静态方法

    1 PowerMock静态方法 写单元测试时 经常会遇到测试方法体内调用了某些工具类的静态方法的情况 而这些静态方法一般是读取配置中心里的文件数据 或者是一些其他涉及到需要启动项目的操作 往往这些操作会造成Mock单元测试的不彻底 有些流水
  • 排序算法之快速排序

    高快省的排序算法 有没有既不浪费空间又可以快一点的排序算法呢 那就是 快速排序 啦 光听这个名字是不是就觉得很高端呢 假设我们现在对 6 1 2 7 9 3 4 5 10 8 这个10个数进行排序 首先在这个序列中随便找一个数作为基准数 不