快速排序

微信小程序返回按钮的隐藏玩法:用onShow实现数据自动刷新(附完整代码) 本文深入探讨了微信小程序中用户点击返回按钮后,如何利用onShow生命周期函数实现页面数据的自动刷新。文章对比了onLoad与onShow的差异,提供了从基础的本地存储标记到进阶的EventChannel事件通信,再到状态管理库的多种解决方案,并附有完整的代码示例,帮助开发者构建流畅的用户体验。 阅读详情

排序算法是各种笔试,面试最常考到的一类题目,提到排序,一定会要求提供一种高效的方法,所以就不得不说一下快速排序了。快嘛!

写出快速排序一定要先理解什么是枢纽元(pivot),枢纽元就是每次执行快排需要参照的那个元素。

最常见的选择pivot的方法是选择第一个元素。此外还有最后一个元素,随机选择,中值法等等。

比如 20,34,4,53,43,42,6,67,193  选择20为pivot经过一趟快速排序后会达到:

       6,4,20,53,43,42,34,67,193  过程可参见动画http://www.jcc.jx.cn/xinwen3/news/kj/flash/2004/0426/1306.htm

由此我们也可以看到快速排序每次的目的就是找到枢纽元的准确位置,

即 小于枢纽元的数 | 枢纽元 | 大于等于枢纽元的数

所以只要你能每趟排序达到这样的效果,就可以条条大陆通罗马了。

 

实现快速的排序的难点在于, 

 (1) 如何停止递归,即什么时候return?

 比较容易记忆的方式是:在 start>=end 时 return,很明显这时表示待排序的序列只有一个或0个元素。不需要做任何处理,所以返回。

 (2) i,j越界问题。

      编写程序时,只要单独考虑到以下三条特例情况,如果不出问题通常可以满足越界要求了:

      1.  2个元素的排序,

      2.  i++到end时,

      3.  j--到为-1时。

 (3) 如何停止i++,j--操作,即什么时候算是完成一趟快速排序操作?

 通常i++,j--外面要包一层循环,问题也就变成了,如何停止这个循环。

 比较常见的做法是:

             do{

             }

             while(i<j)

 当然也可用:

             for(; ;)

             {

                if (i < j)

                {...}

                else

                  break;

             }

 (4) 如果序列有相等元素怎么办?

 一种常见方法是,对于j--操作要求判断条件为 <= 而不是<

具体对于这4个难点的解决参见下面的代码片段:

 //注意,该函数是以最后一个元素p[end]为pivot。
QuickSort(int p[], int start, int end)
{
    if (start >= end) //(1)此时无需排序,所以返回。(2).1 这还保证了,如果只有2个元素时,j=end-1 =1>0
        return;
    int i = start, j = end - 1;
    int tmp;
    do
    {
        while(p[i]<p[end]){i++;}
        while(p[j]>=p[end]){j--;} //(4) 解决相等元素问题。
         if (i<j)
           swap(p[i], p[j]);
        else
           swap(p[i], p[end]);//确定pivot的准确位置。
    }
    while(i < j);
    //(3)至此完成了一趟快速排序得到:小于pivot的数 | pivot | 大于等于pivot的数

    QuickSort(p, start, i-1); //对小于pivot的数进行快速排序。
    QuickSort(p, i+1, end); //对大于等于pivot的数进行快速排序。
    //(2).2 如果i到end时,即end前的所有元素都小于pivot,会发现,i+1>end了,即递归调用时会立刻返回,所以不会发生p[i]操作越界的现象,因为根本就没机会往下走。(2).3同理。
}

下面给一段可执行代码:

 

#include <iostream>
using namespace std;

void QuickSort(int p[], int start, int end)
{
    if (start >= end)
    {
        return;
    }
    int i=0, j=0, tmp=0;
    i = start;
    j = end-1;

    do
    {

        // i++是不会越界的,因为随着i++,p[i]最后会指向最后一个元素即等于p[end], 这时p[i]<p[end]不再成立,i将停止增加。
        while(p[i] < p[end])
        {
            i++;
        }

        //吸纳网友回复,j--的确存在越界的情况,即j--会最后为-1,但p[-1] 是个未知内存地址,初值应该是-2147483648(见后面论据),所以会有p[j] < p[end],终止循环,除了下面1种例外。

          希望大家也能随我更深入的看一下这个问题,严格讲会有一种情况出现bug:p[end] = -2147483648 如:{20,34,4,53,43,42,6,67,-2147483648}, 这时p[j]>=p[end]将一直成立,我在自己电脑win7+vs2010测试: -2147483637仍然能过,所以我猜测系统给未初始化的地址初值是-2147483648(2^31 = 2147483648 = -2147483648)。 很隐蔽的bug!!  当然越界总归不好,另外,两层循环也显的有些臃肿,做了一个更新版QuickSort,见下面。


        while(p[j] >= p[end])
        {
            j--;
        }
        if (i<j)
        {
            tmp = p[i];
            p[i] = p[j];
            p[j] = tmp;
        }
        else
        {
            tmp = p[i];
            p[i] = p[end];
            p[end] = tmp;
        }
    }
    while(i<j);

    QuickSort(p, start, i-1);
    QuickSort(p, i+1, end);
}

void PrintArrary(int data[], int size)
{
    for (int i=0; i<size; ++i)
    {
        cout <<data[i]<<" ";
    }
    cout<<endl;
}

int main(int argc, const char** argv)
{
    int array[]= {20,34,4,53,43,42,6,67,193};
    int size = sizeof(array)/sizeof(int);
    QuickSort(array, 0, size - 1);
    PrintArrary(array, size);
    return 0;
}

 

更新版QuickSort:

void QuickSort(int a[], int low, int high)
{
    if (low >= high)
    {
        return;
    }
    int i = low;
    int j = high;
    int pivot = a[low];
    while(i <= j)
    {
        if (a[i] <= pivot)
        {
            i++;
        }
        else if (a[j] > pivot)
        {
            j--;
        }
        else
        {// swap a[i], a[j]
            int tmp = a[i];
            a[i] = a[j];
            a[j] = tmp;
            i++;
            j--;
        }
    }
    // swap a[low] , a[j]
    a[low] = a[j];
    a[j] = pivot;
    j--;
   
    QuickSort(a, low, j);
    QuickSort(a, i, high);   
}


但我们要警惕,快速排序算法曾被认为,理论上快速高效,但实际中却不可能正确编写的算法。

为什么这么说,这最主要源自枢纽元(pivot)的选择方法不唯一。

比如上面列举的以第一个或最后一个元素为pivot的方法就不是一个好的方法,存在隐患。

快速排序的平均时间复杂度是 O(nlogn) 但如果序列是预排序的或是反序的,采用这种pivot方式的快速排序花费的时间将变为二次的。即O(n2)但预排序(或大部分预排序)又是一种很常见的数据提供方式。

所以更为安全的办法是采用三数中值法选取pivot:最左边的数,最右边的数,中间数三个位置的数的中值为pivot

20,34,4,53,43,42,6,67,193  left=20, right=193, middle=43, 20<43<193所以选择43为pivot。

将pivot与right互换,然后便可以按照上面提供的end作为pivot的算法进行快速排序了。

20,34,4,53,193,42,6,67|43    i从第一个数开始,j从倒数第二个数开始。

 i                           j

大厂硬件机试选择题与判断题解析-卷1 本文精选30道硬件工程师机试题目,涵盖模拟电路、数字电路、PCB设计三大方向。模拟电路部分重点考察运算放大器、滤波器、整流电路等核心知识;数字电路部分聚焦计数器、电平转换等关键技术;PCB设计部分强调高速信号处理、阻抗控制等实践要点。题目均来自华为、小米等大厂真题,剔除基础题,每道题附详细解析,包括正确答案推导过程及相关公式说明。特别针对易错概念(如负反馈类型判断、Q值与带宽关系等)进行重点解析,帮助考生系统掌握硬件设计的核心考点和解题思路。 阅读详情

相关推荐

华为设备有关用户名密码的策略配置

命令用来开启对密码进行复杂度检查功能,设备默认已经是开启状态。1、密码长度大于等于12位,含数字大小写字母和特殊符号。2、设置密码更换周期为90天。取值范围8-16,默认长度为8位。登录失败后锁定时间大于15分钟。3、登录失败次数小于5次。4、登录超时30分钟以内。

简单的创作,希望可以帮助到跟我一样的学习者! 7840

选择排序-简单选择排序

void SelectSort() { int i, j, min; int n = t.length; for (i = 1; i < n; i++) { min = i; // 找出最小元素下标. for (j = i+1; j <= n; j++) if (t.r[min] > t.r[j]) min = j; // 与i比较,

fu_sheng_的博客 254

AI时代敏捷开发新范式——意图驱动开发IDD

具体的功能代码、单元测试、集成测试用例,以及最终可运行的、支持PlantUML的Markdown转Word工具新版本。:业务方(如技术文档团队)反馈,现有的Markdown转Word工具在处理包含PlantUML代码块的文档时,无法正确生成图表,导致技术方案、架构图等关键信息丢失,严重影响了文档交付质量和团队效率。这不仅带来了交付周期显著缩短、资源效能倍增的可观收益,更深远的意义在于,它描绘了未来软件工业化、智能化的新图景:一个由精准意图驱动、AI自主执行、人类智慧引领的敏捷、高效、高质的新世界。

LiuJunjiang的专栏 552

quick sort

快速排序 每经过一趟快排,轴点元素必须就位,也就是说,一趟下来至少有一个元素在其最终位置。 第一趟下来,确定一个位置 第二趟排序,又确定一个或者两个元素位置, 当第一趟元素确认的位置为最左或最优时,第二趟排序只能确定一个位置 当第一趟元素确认位置不是最左或最右时,第二趟能确认2个位置。 所以,两趟排序共确认2 或3个元素位置。 ...

weixin_42813923的博客 1105

基于Vivado2025的UltraScale+时序收敛优化实战案例

深入解析在Vivado2025环境中针对UltraScale+架构的时序收敛挑战,结合实际设计案例,分享关键优化策略与操作技巧,显著提升设计性能与收敛效率。vivado2025的更新特性为时序优化带来新机遇。

weixin_33660045的博客 346

MiniMax H3本地部署与ComfyUI集成实战:从环境配置到提示词优化

文本到视频生成是AI内容创作领域的关键技术,它基于扩散模型等深度学习原理,将自然语言描述转化为连贯的动态视觉序列。这项技术的核心价值在于大幅降低了视频制作的门槛,为短视频创作、概念可视化、教育内容生成等场景提供了高效工具。在实际工程实践中,成功部署和运行此类模型,如近期备受关注的MiniMax H3,需要精准处理环境配置、显存优化和提示词工程等环节。其中,解决“CUDA error: no kernel image is available”等版本兼容性问题,以及针对“8G显存”等有限资源进行参数调优,是确

weixin_33674976的博客 479

快速排序总结

递归版 每一次快速排序都是确定一个元素的位置,然后对左右两边的区域做相同过程,直到左边大于等于右边界。 一次快速排序就是以左边界的值为中心,小于它的交换到左边,大于它的交换到右边。 class Solution { public void sortColors(int[] nums) { process(nums,0,nums.length-1); } public void process(int[] nums, int left, int right){

31楼下小黑的博客 506

交换机救命命令手册:华为 & 思科平台最全运维指令速查表

很多时候,真正拉你一把的不是“高深理论”,而是你手里有没有一份靠得住的命令速查表。这篇文章,希望能成为你“进可调试,退可排障”的一份救命卡片。

HuaweiLab_Peach的博客 1518

快速排序--笔记

思路:将排序数组的第一个元素确定为基准点元素,开始循环直到左右的指针相遇,每次循环都是在调整基准点元素的位置,比基准点元素小的元素放到左边,大的元素放到右边,一轮循环下来确定基准点元素的位置,然后通过递归算法,逐个确定所有元素的位置。快速排序核心思想:每次至少确定一个元素(基准点元素)的位置。

cheng020316的博客 254

代码生成 | 安时积分法模型搭建

安时积分法是电池电量计量最基础的方法,今天我们用simulink建模的方式做一个安时积分模型,从而更好地理解安时积分的思想也掌握建模的基础操 ​新建文件 打开MATLAB启动simulink新建一个模型文件 定义变量 和手写代码一样,先定义几个后面要用到的变量,在simulink建模时新建变量用Data Store Memory模块。双击填入要定义的变量名,然后在signal attributes赋初值 如此方法新建四个变量current(电流)初值1000mA、tatol_cap(总容量

ningvay的博客 1万+

2026滑块验证码终极实战:缺口检测算法+人机轨迹模拟,识别率从60%飙升至95%全方案

**摘要:2026年AIGC技术发展导致传统验证码失效,滑块验证码成为主流防护手段。本文深入分析了传统方案识别率低的原因,并提出多级检测融合和行为拟合优化方案。通过图像预处理优化、三级缺口检测引擎(差分图像法、Hu矩轮廓匹配、YOLOv8n模型兜底)将识别率提升至99.2%。同时针对轨迹模拟环节,设计了包含抖动特征、时间随机性和个体差异的行为模型,使通过率从12%提升至87%。该方案解决了传统方法在缺口定位精度和轨迹真实性方面的核心痛点,为应对新一代验证码风控提供了完整的技术框架。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1902

排序算法总结(6)--快速排序

快速排序的介绍和实现

liqiutuoyuan的博客 727

HTOL集成电路老化测试学习总结-20250510

电子元器件的可靠性在产品开发中至关重要,尤其是在微电子技术迅速发展的今天。电子元器件的失效率通常遵循“浴盆曲线”,分为早期失效期、可使用期和老化期。为了评估芯片的可靠性,常采用高温操作寿命测试(HTOL),通过高温和高压加速芯片老化,以筛选出早期失效的芯片并评估其长期可靠性。HTOL测试中,芯片在高温下运行并监控其性能变化,通过阿伦尼乌斯公式计算加速因子,预测芯片的失效率和寿命。此外,Burn-in测试用于加速芯片老化,提前发现并剔除不合格产品,而早期失效率测试(ELFR)则用于评估产品初期使用阶段的可靠性

歌颂苦难的行为是无耻的; 2103

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

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

liyanan的博客 3041

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

什么是快速排序?

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

热爱编程的菜鸟 5605

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

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

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

子居的博客 1193

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

手写快速排序

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

God Liao On The Way 1万+

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

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

hula_hula_的博客 1635

快速排序 与 随机快速排序 算法分析

快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要Ο(n log n)次比较。在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。 快速排序的优点: (1)原址排序,空间复杂度较小。 (2)虽然最坏情况下(有序数组)

hustyangju的足迹 4119

快速排序之三路快速排序

之前介绍了快速排序和优化版的快速排序 下面再来介绍一种 【三路快速排序】 【代码实现】 //三路快速排序 template<typename T> static void quickSort3Ways(T arr[], int n) { __quickSort3Ways(arr, 0, n-1); } template<typename T> static void

qq_41033011的博客 377

经典快速排序及双路三路快速排序

文章总结: 快速排序是20世纪最重要的10大算法思想之一,也是目前公认的最快的排序算法之一,其主要思想是递归与分治,把一个复杂的问题分成多个的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。本文介绍了经典的快速排序与及其两个改进:双路与三路快速排序。 1.经典的快速排序算法 经典的快速排序算法的基本思想是:在序列中选定一个基准值,遍历序列,将序列分为两部分,一部分大于基准值,一部分小于基准值,再递归地对这两部分数据进行快速排序,直到整个序列有

weixin_38429450的博客 568

快速排序和随机快速排序

原创作品 转载请注明出处http://blog.youkuaiyun.com/always2015/article/details/46523531一、问题描述实现对数组的普通快速排序与随机快速排序 (1)实现上述两个算法 (2)统计算法的运行时间 (3)分析性能差异,作出总结二、算法原理:1、快速排序快速排序是对冒泡排序的一种改进。它的基本思想是:选取一个基准元素,通过一趟排序将要排序的数据分割成独

去实验室,奔跑吧 1万+

快速排序和快速排序的随机化版本

1、概述 快速排序算法中,采用分治思想,每次调用partition函数对当前规模的数组进行处理,如何处理呢: (1)选择一个主元素,何为主元素,可以理解为电视中主角,此主角在这次调用partition(arr,left,right)后将会找到它的最终位置,使得它的左侧数据都比不大于它,右侧元素都不小于它(由此可知,此快速排序算法是原址排序,直接在原数组中进行排序),同时这个方法将会这个主元的下...

wangqsse的博客 535
上一篇: 如何构建二叉树
下一篇: 堆排序
midgard
博客等级 码龄21年 88粉丝 21原创
评论 11
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值