【算法基础】快速排序(模板)

news2024/11/23 19:49:26

在这里插入图片描述

👦个人主页:Weraphael
✍🏻作者简介:目前正在学习c++和算法
✈️专栏:【C/C++】算法
🐋 希望大家多多支持,咱一起进步!😁
如果文章有啥瑕疵
希望大佬指点一二
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注😍


目录

  • 一、快速排序步骤
  • 二、代码模板
  • 三、边界问题
    • 3.1 为什么要指针要指向边界,然后使用`do while`而不直接使用 `while`?
    • 3.2 为什么移动移动`i`和`j`的条件分别是 `< x` 和 `> x`,而不是一开始所说的`<= x`和`>= x`
    • 3.3 当分界点为左端点x = a[0]
    • 3.4 当分界点为右端点a[n - 1]
    • 3.5 当x = a[(l + r) / 2]
    • 3.6 当x = a[(l + r + 1) / 2]
  • 四、算法分析
  • 五、总结

一、快速排序步骤

在这里插入图片描述

  1. 第一步:要确定一个分界点x分界点可以取左端a[0]、右端a[n - 1]、中间值a[(l+r) / 2]或者是随机值
  2. 第二步:调整区间。快速排序的思想是分治。 所以,要使分界点左部分≤x,右部分≥x (升序)。
  3. 第三步:递归处理左右两个部分。

Q:如何将数组一分为二,使≤x在左边,≥x在右边呢?

法一:暴力做法

  1. 开辟两个数组分别是c[]q[]
  2. 再扫描原数组a[],把≤x的元素放在c[]中,≥x放在q[]中。
  3. 最后先将c[] 放入a[],再把b[]放入a[]

法二:双指针做法(推荐)

  1. 首先先让指针i++向中间寻找元素,直到指向的a[i] ≥x停下
  2. 同样地,再将指针 j - -向中间寻找元素,直到指向的a[j] ≤x停下
  3. 当条件满足 i < j,就将这两个元素交换(swap)
  4. 当循环结束,指针j最终就一定会在指针i的前面

举个例子来验证双指针算法:

假设要升序排序 1 3 5 2 4,并设分界点x = 3

  • 先移动i,直到i指向的元素≥3停下
    在这里插入图片描述
  • 再移动j,直到j指向的元素≤3停下​​
    ​​在这里插入图片描述
  • 当条件满足i < j,则交换
    在这里插入图片描述
  • 接着继续移动i,直到i指向的元素≥3停下
    在这里插入图片描述
  • 再移动j ,直到j 指向的元素≤3停下
    在这里插入图片描述
    最后,我们会发现,j最终停在了i的前面

二、代码模板

void quick_sort(int a[],int l,int r)
{
	// //如果数组中就一个数或者没有数,就没必要再排序(递归出口) 
    if(l >= r) return; 
    // 1. 确定分界点x
    int x = a[(l + r) / 2]; 
    // 2. 调整区间
    // 将指针指向边界(边界问题)
    int i = l - 1, j = r + 1;
    while (i < j)
    {
        do i++; while(a[i] < x);
        do j--; while(a[j] > x);
        if (i < j) swap(a[i],a[j]);
    }
    // 3. 递归处理左右两部分
    //递归处理左部分,也就是<x的部分
    quick_sort(a, l, j);
    //递归处理右部分,>x的部分
    quick_sort(a, j + 1, r);
}

三、边界问题

3.1 为什么要指针要指向边界,然后使用do while而不直接使用 while?

原因是:以while为例,假设数组中有 相同的元素,会发生死循环

举个例子,假设排序 3 1 3 2 4,并设分界点x = 3

  1. 先判断i
    在这里插入图片描述
  2. 再判断j
    在这里插入图片描述
  3. 当条件 i < j ,交换元素
    在这里插入图片描述
  4. 接着再判断i ,而j不满足条件会继续指向3
    在这里插入图片描述
    最后你会发现,就会一直死循环交换3

3.2 为什么移动移动ij的条件分别是 < x> x,而不是一开始所说的<= x>= x

如果分界点x,恰好是数组中最大值,会导致越界。
同理,如果分界点又恰好是数组中最小值,也会导致越界。

3.3 当分界点为左端点x = a[0]

递归部分就不能使用quick_sort(a, l, i - 1)quick_sort(a,i,r),会导致 死递归
举个例子
当数组只有12在排序时,左端点分界点x = 1
在这里插入图片描述
因此,到时候ij会同时指向1
此时i = 0j = 0l = 0r = 1
对于第一个递归:quick_sort(a,0,- 1),相当于数组内没有值可以交换。
对于第二个递归:quick_sort(a, 0, 1),这时,就一直就这两个数交换,导致死递归。

3.4 当分界点为右端点a[n - 1]

递归部分就不能使用quick_sort(a,l,j)quick_sort(a,j + 1,r),会导致 死递归
和例子3.3是一样的
当数组内部还是只有12两个元素,这时右端点x = 2
在这里插入图片描述
因此,到时候ij会同时指向2
此时i = 1j = 1l = 0r = 1
第一个递归quick_sort(a,0,1),这时,就一直就这两个数交换,导致死递归

3.5 当x = a[(l + r) / 2]

递归部分不能使用quick_sort(a,l,i - 1)quick_sort(a,i,r)
还是同样的例子,假设还是只有12在排序,这时分界点x = a[(0 + 1)/2] = a[0] = 1,这种情况就和3.3是一样的了。

3.6 当x = a[(l + r + 1) / 2]

递归部分就不能使用quick_sort(a,l,j)quick_sort(a,j + 1,r)
还是同样的例子,数组还是只有1,2两个元素,这时分界点x = a[(0 + 1 + 1)/2] = a[1] = 2,这中情况就和3.4是一样的

四、算法分析

  1. 时间复杂度
    快速排序最坏时间复杂度是O(n^2),最好的时间复杂度为O(nlogn)

  2. 空间复杂度
    空间复杂度是O(1),因为没有用到额外开辟的集合空间。

  3. 算法稳定性
    快速排序是不稳定的排序算法。因为我们无法保证相等的数据按顺序被扫描到和按顺序存放。

五、总结

  1. x=a[l]或者x=a[(l + r) /2],只能用
//左半部分递归
quick_sort(a, l, j); 
//右半部分递归
quick_sort(a,j + 1, r);
  1. x=q[r] or x=q[l+r + 1>>1],只能用
//左半部分递归
quick_sort(a,l,i - 1);
//右半部分递归
quick_sort(a, i, r);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/703341.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣题库刷题笔记17--电话号码的字母组合

1、题目如下&#xff1a; 2、个人Python代码实现&#xff1a; 还是先记录一下思路&#xff0c;首先这种类型的题&#xff0c;需要自定义一个字典对应题目中的电话号码和数字。其次&#xff0c;个人的思路是&#xff0c;先读取字符串第一个字符&#xff08;digits[0]&#xff09…

云原生(第二篇)k8s-二进制搭建

准备五台机器&#xff1a; master01&#xff1a;192.168.169.10 node01&#xff1a;192.168.169.40 node02&#xff1a;192.168.169.50 master02&#xff1a;192.168.169.60 负载均衡nginxkeepalive01&#xff08;master&#xff09;&#xff1a;192.168.169.20 负载均衡…

记一次Native memory leak排查过程 | 京东云技术团队

1 问题现象 路由计算服务是路由系统的核心服务&#xff0c;负责运单路由计划的计算以及实操与计划的匹配。在运维过程中&#xff0c;发现在长期不重启的情况下&#xff0c;有TP99缓慢爬坡的现象。此外&#xff0c;在每周例行调度的试算过程中&#xff0c;能明显看到内存的上涨…

Windows开启telnect

1、Telnet是什么&#xff1f; Telnet 是一种网络协议&#xff0c;用于通过网络远程登录到远程计算机或设备上。它允许用户在本地计算机上使用命令行界面&#xff08;命令提示符&#xff09;与远程主机进行交互&#xff0c;就像直接在远程主机上操作一样。Telnet 协议使用 TCP/I…

【需求实现】Tensorflow2的曲线拟合(三):Embedding层

文章目录 导读Embedding的维度问题Embedding的输入输出比较容易踩的坑input_shape与input_length的对应关系built属性 导读 这是填曲线拟合第一篇的坑&#xff0c;有关Embedding层的问题。 Embedding的维度问题 首先是上次我们提到的Embedding层&#xff0c;他确实能够做到将…

预约Oracle OCP认证考试的保姆式流程

Oracle OCP认证考试的预约流程涉及到Oracle的SLS培训记录&#xff0c;因此相当复杂。本文进行了详细地说明&#xff0c;每一步都有截图&#xff0c;有需要的同学建议收藏。 关于号主&#xff0c;姚远 Oracle ACE&#xff08;Oracle和MySQL数据库方向&#xff09;。Oracle MAA…

智能体重秤方案PCBA方案设计

智能体重秤是一款高精度、便捷、多功能的健康管理工具&#xff0c;旨在帮助用户监测和控制体重&#xff0c;达到健康管理与减肥的目的。该产品融合了先进的科技技术&#xff0c;结合了人体工程学设计&#xff0c;具有美观、易用的特点。以下将从结构、参数、原理和应用方面为大…

电涌(浪涌)保护器防雷保护级别

浪涌保护器实际就是压敏电阻&#xff0c;具有高通低阻的特性。当电网在不超过最大持续运行电压的情况下运行时&#xff0c;两个电极之间呈高阻状态。由于雷击的能量是非常巨大的&#xff0c;需要通过分级泄放的方法&#xff0c;将雷击能量逐步泄放到大地。 第一级防雷器可以对…

mmyolo框架实现在VOC数据集上复现Yolov6教程(详细)

写在开头&#xff0c;最近学习mmyolo的框架&#xff0c;想着它能将所有配置都写在一个config文件里&#xff0c;只需要改配置文件就可以改动模型&#xff0c;感觉挺方便的。 就想着Yolov6用mmyolo框架来实现,但mmyolo并没有提供v6的voc实现配置&#xff0c;v5是有的(看下图)&am…

软件测试技能,JMeter压力测试教程,取样器之测试活动(十八)

目录 前言 一、测试活动(Test Action) 二、Pause 设置暂停 三、Stop 停止 四、循环设置 五、跨线程组使用 前言 如果想在请求之后加等待时间如何做呢&#xff1f; 如果希望在 sampler 执行完之后再等待&#xff0c;则可使用取样器里面的测试活动 (Test Action) 一、测…

10个Salesforce集成项目最佳实践,助力成为专家!

随着企业越来越关注数据驱动的决策方法&#xff0c;集成多个系统成为了Salesforce 实施不可或缺的一部分。无论该项目是Salesforce的传统CRM迁移还是新的CRM实施&#xff0c;Salesforce CRM与ERP以及其他业务关键系统的集成都是需要考虑的重要策略。 集成项目的成功很大程度上…

Vue-pdf踩坑记录

最近在公司的一个项目中&#xff0c;需要在线预览PDF文件。基于vue-admin-electron的模板中开发。开发机系统为Windows&#xff0c;使用的框架为electron-vue。 坑1&#xff1a;在通过vue-router路由到含有vue-pdf组件的页面时报&#xff1a;“syntaxError: Unexpected token …

《移动互联网技术》 第十章 系统与通信: 掌握Android系统的分层架构设计思想和基于组件的设计模式

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

玩转代码|三个惊艳的黑科技代码,每一行代码都有惊讶的效果

目录 显示忘记密码 解除网页限制 去除视频logo 今日优质代码推荐 实现效果 实现过程 1. 简单的 Html 和 CSS 2. 创建 canvas画布 3. 获取鼠标点击位置 4. 实现鼠标点击产生烟花的初级形态 5. 实现烟花散开 6. 实现拖尾效果以及随机颜色 7. 实现烟花重力下坠 8. 实…

深度学习模型训练的全流程

目标是使用Pytorch来完成CNN的训练和验证过程&#xff0c;CNN网络结构。需要完成的逻辑结构如下&#xff1a; 构造训练集和验证集&#xff1b; 每轮进行训练和验证&#xff0c;并根据最优验证集精度保存模型。 # 将自定义的Dataset封装成一个Batch Size大小的Tensor&#xf…

threejs后期处理

个人博客地址: https://cxx001.gitee.io 1. 如何使用Threejs的后期处理 后期处理就是在场景渲染完后&#xff0c;最后对场景显示效果调整的手段。 使用后期处理步骤&#xff1a; &#xff08;1&#xff09;创建THREE.EffectComposer对象。(效果组合器) &#xff08;2&#x…

指定某个时间,计算和当前时间间隔几天几时几分

dateDiff(startTime,endTime) {let t1 new Date(startTime).getTime()*1000; //开始时间 2023-06-29 10:00:00let t2 new Date(endTime).getTime()*1000; //结束时间 1688090400000000 2023-06-30 10:00:00 1688092230000000 2023-06-30 10:30:30let dateTime 1000 *…

小程序反编译

第一步&#xff1a;下载软件 根据把博客下载好三个软件 夜神模拟器 RE文件管理器 Node.js 第二步&#xff1a;打开模拟器中的 “微信” 第三步&#xff1a;点击要下载的小程序 并 记录当时的时间 方便一会查找pkg文件 第四步&#xff1a;打开文件资源管理器 第五步&#xff1a…

PyTorch的ONNX结合MNIST手写数字数据集的应用(.pth和.onnx的转换与onnx运行时)

在PyTorch以前的模型都是.pth格式&#xff0c;后面Meta跟微软一起做了一个.onnx的通用格式。这里对这两种格式文件&#xff0c;分别做一个介绍&#xff0c;依然使用MNIST数据集来做示例 1、CUDA下的pth文件 那pth文件里面是什么结构呢&#xff1f;其实在以前的文章就有介绍过…