快速排序

快速排序及优化方案 文章目录快速排序及其优化方案1. 快速排序的流程2. 快速排序的实现时间复杂度计算3. 快速排序优化随机获取基准值进行优化3.2二路快速排序原理:思想:4. 总结 快速排序及其优化方案 1. 快速排序的流程 首先设定一个分界值,通过该分界值将数组分成左右两部分。 将大于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边,而等于分分界值的部分放在相对中间的部分。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于分界值,相对中间的部分的的数据等于分界值。 然后,左边和右边的数据可以独立排序 阅读详情
1.快速排序的介绍:
2.传统快速排序及其时间复杂度。
3.快速排序的几种改进方案。
1.快速排序的介绍

快速排序可能是应用的最为广泛的排序算法了,快速排序的主要优点有:
1.原地排序.
2.大多数情况下,它的时间复杂度都是NlogN.
但是它的缺点也很明显,它是一个不稳定的算法,在要排序的数组已经有序的情况下,它的效率能降到N的平方。

2.传统的快速排序实现及其时间复杂度
2.1递归实现的快速排序实现

递归实现的快速排序比较容易让人理解,代码也比较简单,其中最重要的就是要写好partition函数,partition函数的接口如下:

int partition( int data[], int start, int end ); //[start, end)

partition函数的主要功能是在data数组的start~end区间找到一个哨兵元素,找到这个哨兵元素排序后的位置,并且保证这个位置之前的所有元素都小于等于哨兵元素,这个位置之后的元素都大于哨兵元素。
cheat is cheap, show me your code…下面给出partition函数的一种实现方法:

        int partition( int data[], int start, int end )
        {
            int i = start, j = end;
            int sentry = start;
            while ( 1 )
            {
                //从前往后找到小于哨兵的元素
                while ( data[++i] < data[sentry] )
                    if ( i >= end )
                        break;
                //从后往前找到大于哨兵的元素
                while ( data[--j] > data[sentry] )
                    if ( j < start )
                        break;
                if ( i >= j )
                    break;
                int temp = data[i];
                data[i] = data[j];
                data[j] = temp;
            }
            //将data[start]放到合适的位置,
            //这里注意一定是start和j交换。
            int temp = data[j];
            data[j] = data[start];
            data[start] = temp;
            return j;
        } 

图片往往比文字更能清楚的说明问题,这张图是使用快速排序排序数组{K, R, A, T, E, L, E, P, U, I, M, Q, C, X, O, S}的切分轨迹图。
快速排序过程
partition函数完成之后切记要先测试一下再接着写,在写完每一个小功能之后都先要确保这个功能实现正确之后再进行下一步。
接下来就是快速排序的主体部分了,因为快速排序在递归的时候,需要一些适当的参数来传递信息,所以为了保证排序函数接口的统一性,额外增加了一个_sort函数来进行排序的主要过程。下面是代码实现。

    //[start, end)
    void _sort( int data[], int start, int end )
    {
        if ( start >= end )  return ;
        int j = partition( data, start, end );
        _sort( data, start, j );
         _sort( data, j+1, end );
    }

    void quick_sort( int data[], int size )
    {
         _sort( data, 0, size );
    }
2.2快速排序时间复杂度

对于一个随机数组,在最好的情况下,快速排序每次都能将数组各分成一半,这个时候快速排序的效率能达到最好,在最坏的情况下,快速排序划分的数组每次都有一个没有元素,这时候快速排序的效率最低。
但是总的来说,快速排序的时间复杂度能控制在1.39NlgN之内。

3.快速排序的几种改进方案
1.随机快排

随机快排的出现是为了应对快速排序的最坏情况的出现,因为如果被快排排序的数组是一个已经排好序的数组,那么普通快排每次选取的都是区间的第一个元素,每次分割之后的两个子数组中肯定会有一个子数组为空,所以快排的最坏情况就会出现。

随机快排为了应对这中情况,每次选取哨兵元素都是从要排序的区间中随机选取一个,所以最坏情况出现的几率会大大降低,随机快排应该算是一个比较稳定的排序方法。

为了实现快速排序,只需要实现一个_random函数,这个函数的接口如下:

int _random( int start, int end );

这个函数会返回区间[start, end)之间的一个随机数,产生随机数直接调用c语言的函数库即可。下面是一个参考的实现代码:

        int _random( int start, int end )
        {
            int n = end - start;
            //rand()%n会产生[0, n)之间的一个随机数, rand()%n+start会产生[start, end)之间的随机数
            int randomNum = rand()%n + start;
            return randomNum;
        }

将普通快排变为随机快排只需要将上面给出的partition函数里面的

int sentry = start;

改为

int sentry = _random(start, end);

就行了。

2.快速排序中融入插入排序

毫无疑问,对于小数组排序来说,使用插入排序要比使用快速排序快的多,不管在使用快速排序处理多大的数组,在递归的底层我们都要对一些小数组进行排序,这个时候最好的解决方案并不是继续使用快速排序。因此在排序小数组的时候,我们采用插入排序的提高算法的运行效率。

将小数组的排序从快速排序改为插入排序也是比较容易的,只需要将_sort函数里面的

if (start >= end) return ;

改成

if (start + M >= end) { insert_sort( data, M ); return ; }

就行了。至于M,已经有人帮我们证明了M取5~15之间的任意值时算法效率是值得满意的。

3.通过三取样切分优化快速排序

三取样切分跟随机快排一样,也是从寻找最优的切分点这个方向上来优化快排。
三取样切分即是使用数组中的小部分元素的中位数来切分数组,这样做的切分更好,但是会带来计算中位数的负担,人们发现将取样大小设为3并用大小居中的元素切分效果最好。

4.熵最优的排序

熵最优的排序主要是为了处理数组中有大量重复元素的情况,如果数组中有大量重复的元素,如果不考虑对重复元素做特殊处理,就会少了一个优化的好机会,比如,一个元素全部重复的数组就不需要在进行排序了。

一个简单的想法就是将数组的元素分成三部分,大于哨兵的,小于哨兵的和等于哨兵的。这个问题有一个解法,就是Dijkstra解法。

Dijkstra解法的主要思路是:从左到右遍历数组一次,维护一个指针lt,使得data[lo…lt-1]的所有元素都小于哨兵,一个指针gt,使得data[gt+1…hi]之间的元素都大于哨兵,维护一个指针i,使得data[lt…i-1]之间的元素都等于哨兵,data[i…gt]之间的元素还未处理。

具体的处理过程如下,一开始i等于lo,哨兵值等于v:
(1).如果data[i]小于v,则交换data[i]和data[lt],lt++, i++;
(2).如果data[i]大于v,则交换data[i]和data[gt],gt–;
(3).如果data[i]等于v,i++;

这里给出一个大概的实现思路,具体实现细节,有兴趣的可以继续研究。

    void Dijkstra_sort(int data[], int lo, int hi)
    {
        if ( hi <= lo )
            return ;
        int lt = lo, i = lo+1, gt = hi;
        int v = a[lo];
        while ( i <= gt )
        {
            int cmp = compare( a[i], v );
            if ( cmp < 0 )
                swap( data, lt++, i++ );
            else if ( cmp > 0 )
                swap( data, i, gt-- );
            else
                i++;
        }
        sort( data, lo, lt-1 );
        sort( data, gt+1, hi );
    }

这里给出一个Dijkstra解法的三向切分代码的轨迹图,可以便于理解。
三项切分代码轨迹图

关于快速排序还有几个版本,可以参考我在网上找的这篇文章:快速排序的几个版本

参考资料:《算法》第四版

快速排序(Quick sort) 一、简介 快速排序是(Quick sort)是对冒泡排序的一种改进,是非常重要且应用比较广泛的一种高效率排序算法。 二、算法思路 快速排序是通过多次比较和交换来实现排序,在一趟排序中把将要排序的数据分成两个独立的部分,对这两部分进行排序使得其中一部分所有数据比另一部分都要小,然后继续递归排序这两部分,最终实现所有数据有序。 大致步骤如下: 首先设置一个分界值也就是基准值又是也称为监视哨,通过该分界值将数据分割成两部分。 将大于或等于分界值的数据集中到右边,小于分界值的数据集中到左边。一趟排序过后,左边部 阅读详情

相关推荐

算法介绍——快速排序

快速排序 快速排序是最常用的排序算法。 举例说明 假设我们要对 “6 1 2 7 9 3 4 5 10 8” 这 10 个数进行排序。 C代码实现 # 复杂度分析

程序员「阿基米东」的编程之旅 4万+

快速排序详解

在之前我们已经见识到了一些基础的排序算法,比如冒泡排序,选择排序,插入排序,堆排序,希尔排序了,对于以上的几种排序我们知道希尔排序和堆排序的时间复杂度更小一些,他们的算法优先性对于其他算法还是有很大的差别,而今天我们会介绍一个排序速度如其名的排序--快速排序。快速排序由C. A. R. Hoare在1962年提出,它是一种基于二叉树结构的交换排序算法,它采用了一种分治的策略,通常称其为分治法。

qq_61422622的博客 4万+

实测iOS和安卓大不同!用NFC触发小程序跳转的完整避坑指南(含NFC Tools配置)

本文深入解析iOS与安卓在NFC触发小程序跳转时的核心差异,提供微信与支付宝小程序的NFC实现方案及优化技巧。涵盖跨平台兼容性测试方法论、性能优化策略及异常处理方案,帮助开发者避开常见陷阱,提升跳转成功率。特别针对NFC Tools配置和微信Universal Link使用进行详细指导。

asdfghjkl978564的博客 434

排序——快速排序(Quick sort)

概况 快速排序(Quick sort)是对冒泡排序的一种改进。快速排序由C. A. R. Hoare在1960年提出。 算法思路 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。 快速排序算法通过多次比较和交换来实现排序,其排序流程如下: ......

努力中的老周的专栏 32万+

SAP 对接CBS(http方式)

CLEAR:lv_xml_crc32_string. CONCATENATEcrc32_passwordcrc32_keyi_stringINTOlv_xml_crc32_string. CONDENSElv_xml_crc32_string. CALLFUNCTION'SCMS_STRING_TO_XSTRING' EXPORTING text=lv_xml_crc32_string encoding='8400' "GB...

3598

海康威视iSC平台视频流对接:RTSP、HLS、WS三种协议到底该怎么选?

本文深入分析海康威视iSC平台视频流对接中RTSP、HLS和WebSocket三种协议的优缺点,帮助开发者根据实时性、兼容性和网络环境做出最优选择。特别适合综合安防管理平台的Web视频监控系统开发,提升用户体验和系统性能。

weixin_28365523的博客 692

快速排序(三种方法实现)

快速排序 hoare法(左右指针法) 挖坑法 前后指针法 快速排序优化 非递归实现 快速排序特性

C_Trip的博客 2万+

Vue3 - 详细实现流程图编辑器可视化平台示例代码,打造前端web网页流程图在线编辑绘制操作展示,vue3自定义绘制流程图在页面上画流程图功能(提供各种操作按钮及节点控件,界面美观交互式流程图插件)

vue3,绘制流程图,在线流程图制作,在vue3中实现流程图,vue3做一个制作流程图的功能,vue3流程图组件,vue3流程图,流程图绘制展示,vue3流程图可视化在线编辑源码,基于VUE3的在线绘制流程图工具,vue3+logicflow流程图,绘制动态流程图并自定义节点和线,vue使用logicFlow绘制流程图,生成各种流程图图形可连接点移除,基于Vue的流程图组件,工作流程图,流程编辑器,vue3流程组件,vue-flow绘制流程图,绘制流程图示例demo,vue3 logicflow流程图使用教

🏆 前端领域优质创作者 9968

三种快速排序以及快速排序的优化

1、快速排序的基本思想:    快速排序使用分治的思想,通过一趟排序将待排序列分割成两部分,其中一部分记录的关键字均比另一部分记录的关键字小。之后分别对这两部分记录继续进行排序,以达到整个序列有序的目的。 2、快速排序的三个步骤: (1)选择基准:在待排序列中,按照某种方式挑出一个元素,作为 "基准"(pivot) (2)分割操作:以该基准在序列中的实际位置,把序列分成两个子序列。此时,在

思考,思考,再思考~ 5万+

CloudCompare 二次开发:插件中的 PCL 环境配置与编程

在进行 CloudCompare 的二次开发过程中,我们常常需要使用点云库(Point Cloud Library,简称 PCL)来处理和分析点云数据。在 CloudCompare 的界面中,选中一个点云对象,然后点击菜单栏中的 “插件” -> “MyPluginAction”。插件将对选中的点云对象进行体素滤波处理,并更新显示结果。下面我们将展示一个简单的插件编程示例,该示例使用 PCL 对输入的点云数据进行体素滤波处理。方法进行体素滤波处理,并将结果点云赋值给选中的点云对象。文件并点击 “打开”。

2301_79331387的博客 283

古风仙侠少女三视图提示词,一键生成角色设定

3D中国写实CG风格,CG渲染质感,精细3D建模,PBR物理材质,细腻服装纹理,电影级灯光,丰富表情,高精度场景,次世代引擎画质。平视正交视角,统一光照,纯白背景,无文字无水印,避免强透视和动态变形。3D中国写实CG风格,CG渲染质感,精细3D建模,PBR物理材质,细腻服装纹理,电影级灯光,丰富表情,高精度场景,次世代引擎画质。3D中国写实CG风格,CG渲染质感,精细3D建模,PBR物理材质,细腻服装纹理,电影级灯光,丰富表情,高精度场景,次世代引擎画质。少女,古风仙侠少女气质,灵动、温婉、仙气。

欢迎来到鸾姝淡月博客,专为程序员和编程爱好者打造的技术博客。我们分享编程语言趋势、开发工具、编程哲学、职业发展等,助你掌握新技术,优化技能,激发编程热情。 1081

经典快速排序与随机快速排序

文章目录一、经典快速排序(一)、经典快速排序的实现理论(二)、经典快速排序的代码实现(Java)(三)、经典快速排序的时间复杂度二、随机快速排序(一)随机快速排序的实现理论(二)随机快速排序的代码实现(Java)(三)、随机快速排序的时间复杂度 一、经典快速排序 (一)、经典快速排序的实现理论 经典快速排序是用数组的最后一个数(这里记为 x )进行划分。也就是 &amp;lt;x、=x、&amp;gt;x。 有...

liyanan的博客 3044

使用阿里天池平台训练YOLO目标检测模型

YOLO算法是一种单阶段目标检测算法,由Joseph Redmon等人于2015年提出。与传统的两阶段检测算法相比,YOLO将目标检测问题转化为回归问题,直接预测边界框的位置和类别概率,大大提高了检测速度。YOLOv1: 首次提出YOLO的核心思想,将图像分割成网格,每个网格预测边界框和类别概率。YOLOv2: 引入了批量归一化、锚框等改进,提高了检测精度。YOLOv3: 采用多尺度预测,增强了对小目标的检测能力。

步子哥的博客 1091

双路快速排序

双路快速排序算法是随机化快速排序的改进版本,partition 过程使用两个索引值(i、j)用来遍历数组,将v的元素放在索引j所指向位置的右边,v代表标定值。

fangfan9的博客 2377

基于YOLOv8的野生菌菇检测、识别与分类系统

YOLOv8是YOLO系列模型的最新版本,继承了YOLO系列高效、精确的特点。YOLOv8采用了新的网络架构,并优化了推理速度和检测精度。与传统的目标检测算法(如Faster R-CNN)不同,YOLO模型通过一次前向传播同时完成目标定位与分类,因而具有非常高的计算效率。

YOLO 1284

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

图解快速排序及双路三路快速排序

前言 之前我们介绍了交换类排序中的冒泡排序,这次我们介绍另一种交换类排序叫做快速排序。快速排序的优点是原地排序,不占用额外空间,时间复杂度是O(nlogn)。 当然,对于快速排序来说,它也是有缺点的,它对于含有大量重复元素的数组排序效率是非常低的,时间复杂度会降为O(n^2)。此时需要使用改进的快速排序—双路快速排序,在双路快速排序的基础上,我们又进一步优化得到了三路快速排序。 快速排序 快速排...

子居的博客 1193

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

什么是快速排序?

文章目录快速排序快速排序简介:基本思想原理快速排序法示意图排序演示Java代码 快速排序 快速排序简介: 快速排序是对冒泡排序的一种改进。 基本思想 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都小于或者等于另外一部分的所有数据,然后再按照此方法对这两部分数据分别进行快速排序,整个排序的过程可以递归进行,以此达到整个数据变成有序序列。 原理 设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选 用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它左边,所

热爱编程的菜鸟 5607

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

快速排序——详解

快速排序(英语:Quicksort),又称分区交换排序(英语:partition-exchange sort),简称「快排」,是一种被广泛运用的排序算法。三路快速排序(英语:3-way Radix Quicksort)是快速排序和基数排序的混合。它的算法思想基于荷兰国旗问题的解法。内省排序(英语:Introsort 或 Introspective sort)4是快速排序和堆排序的结合,由 David Musser 于 1997 年发明。内省排序其实是对快速排序的一种优化,保证了最差时间复杂度为。

w_w_wwwww的博客 1375

手写快速排序

快速排序简介快速排序是一种很不错的排序算法,算法复杂度为n*logn。快排使用了分而治之的思想,每次排序是都找到一个基准(我们学习时经常使用第一个作为基准),然后把小于基准的元素放到基准元素的左边,大于基准的元素放到基准元素的右边,这样一次排序下来,基准元素左边都是小于(等于)基准的数,基准右边的元素都是大于(等于)基准的元素了。快速排序关键点就是找到这样一个基准并将其放到恰到的位置。算法思路定义一

God Liao On The Way 1万+

[算法]快速排序与随机快速排序

与归并排序一样,快速排序也运用了分治策略,而随机快速排序是对快速排序的一种优化。

hula_hula_的博客 1636

分治之快速排序以及快速排序为何最快

算法思想 数组排序任务可以如下完成: 1)设k=a[0],将k挪到适当位置,使得比k小的元素都在k的左边,比k大的元素都在k的右边,和k相等的,不关心在k左右出现均可(O(n)时间完成) 2)把k左边的部分快速排序 3)把k右边的部分快速排序 (假设运气比较好,每次基准元素被移动到中间,这样的话时间复杂度为O(nlogn)) 如何在O(n)的时间内将数组分成两半,一般在小于基准值,一般大于基准值? 程序代码 #include<iostream> using namespace std; int

Java硬件工程师的博客 3190

【快速排序】快速排序/第k个数

acwing算法学习笔记 -----快速排序

青竹雾色间.的博客 1998
上一篇: 【CSAPP阅读笔记】之信息的存储
下一篇: 整数表示
Findway_
博客等级 码龄10年 36粉丝 117原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值