【排序算法】快速排序

news2024/11/19 7:47:41

一:基本概念

1.1 介绍

快速排序由C. A. R. Hoare在1962年提出,它是一种基于二叉树结构的交换排序算法,它采用了一种分治的策略,通常称其为分治法。该方法的基本思想是:先从数列中取出一个数作为基准数,然后将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边,再对左右区间重复第二步,直到各区间只有一个数。快速排序是一种不稳定的排序方法,但是他的效率非常快,比肩希尔和堆排序也略胜一筹。

快速排序(Quicksort)是对冒泡排序的一种改进。基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

1.2 排序流程

快速排序算法通过多次比较和交换来实现排序,其排序流程如下:

1、首先设定一个分界值,通过该分界值将数组分成左右两部分。

2、将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。

3、然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。

4、重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。

概括来说为 挖坑填数 + 分治法。

1.3 图解算法

快速排序主要有三个参数,left 为区间的开始地址,right 为区间的结束地址,Key 为当前的开始的值。

我们从待排序的记录序列中选取一个记录(通常第一个)作为基准元素(称为key)key=arr[left],然后设置两个变量,left指向数列的最左部,right 指向数据的最右部。

在这里插入图片描述

1.3.1 第一步

key 首先与 arr[right] 进行比较,如果 arr[right]<key,则arr[left]=arr[right]将这个比key小的数放到左边去,如果arr[right]>key则我们只需要将right–,right–之后,再拿arr[right]与key进行比较,直到arr[right]<key交换元素为止。
在这里插入图片描述

1.3.2 第二步

如果右边存在arr[right]<key的情况,将arr[left]=arr[right],接下来,将转向left端,拿arr[left ]与key进行比较,如果arr[left]>key,则将arr[right]=arr[left],如果arr[left]<key,则只需要将left++,然后再进行arr[left]与key的比较。
在这里插入图片描述

1.3.3 第三步

然后再移动right重复上述步骤
在这里插入图片描述

1.3.4 第四步

最后得到 {23 58 13 10 57 62} 65 {106 78 95 85},再对左子数列与右子数列进行同样的操作。最终得到一个有序的数列。

{23 58 13 10 57 62} 65 {106 78 95 85}

{10 13} 23 {58 57 62} 65 {85 78 95} 106

10 13 23 57 58 62 65 78 85 95 106

1.4 动画展示

在这里插入图片描述

  1. 首先,操作数列中的所有数字
  2. 在所有数字中选择一个数字作为排序的基准(pivot), pivot 通常是随机选择的,在这里为了演示方便,我们选择最右边的数字作为
    pivot
  3. 选取好 pivot 后,在操作数列中选择最左边的数字标记为 左标记 ,最右边的数字标记为 右标记
  4. 将左边的标记向右移动
  5. 当 左标记 达到超过 pivot 的数字时,停止移动
  6. 在这里,8 > 6 ,所以停止移动
  7. 然后将右边的标记向左移动
  8. 当 右标记 达到小于 pivot 的数字时,停止移动
  9. 在这里,4 > 6 ,所以停止移动
  10. 当左右标记停止时,更改标记的数字
  11. 因此,左标记 的作用是找到一个大于 pivot 的数字,右标记 的作用是找到一个小于 pivot 的数字
  12. 通过交换数字,可以在数列的左边收集小于 pivot 的数字集合,右边收集大于 pivot 的数字集合
  13. 交换之后,继续移动 左标记
  14. 在这里,9 > 6 ,所以停止移动
  15. 然后将右边的标记向左移动
  16. 当 右标记 碰撞到 左标记 时也停止移动
  17. 如果左右侧的标记停止时,并且都在同一个位置,将这个数字和 pivot 的数字交换
  18. 这就完成了第一次操作
  19. 小于 6 的都在 6 的左侧,大于 6 的都在 6 的右侧
  20. 然后递归对这分成的两部分都执行同样的操作
  21. 完成 快速排序

二:算法性能

2.1 时间复杂度

2.1.1 理想情况

如果足够理想,那我们期望每次都把数组都分成平均的两个部分,如果按照这样的理想情况分下去,我们最终能得到一个完全二叉树。如果排序 n 个数字,那么这个树的深度就是log2n+1,如果我们将比较 n 个数的耗时设置为 T(n),那我们可以得到如下的公式

T(n)2T(n/2) + n,T(1) = 0  
T(n)2(2T(n/4)+n/2) + n = 4T(n/4) + 2n  
T(n)4(2T(n/8)+n/4) + 2n = 8T(n/8) + 3n  
......
T(n) ≤ nT(1) + (log2n)×n = O(nlogn) 

2.1.2 最坏情况

而在最坏的情况下,这个树是一个完全的斜树,只有左半边或者右半边。这时候我们的比较次数就变为
在这里插入图片描述

2.2 空间复杂度

2.2.1 原地排序

原地快排的空间占用是递归造成的栈空间的使用,最好情况下是递归(log_{2}n)次,所以空间复杂度为O(long2n)
,最坏情况下是递归 n-1 次,所以空间复杂度是O(n)。

2.2.2 非原地排序

对于非原地排序,每次递归都要声明一个总数为n的额外空间,所以空间复杂度变为原地排序的n倍,即最好情况下O(nlog2n)
,最差情况下(O(n^{2}))。

2.2.3 稳定性

不稳定。

三:代码实现

public class QuickSort {
    public static void main(String[] args) {
        int[] arr = {-9, 78, 0, 23, -567, 70, 23, 78, 958, 7, -15698, -56, 515};
        long s = System.currentTimeMillis();
        quickSort(arr, 0, arr.length - 1);
        long e = System.currentTimeMillis();
        System.out.println("arr=" + Arrays.toString(arr));
        System.out.println("quickSort执行时间为:" + (e - s));
    }

    /**
     * 快速排序
     *
     * @param arr   数组
     * @param left  左侧索引
     * @param right 右侧索引
     */
    public static void quickSort(int[] arr, int left, int right) {
        //左下标
        int l = left;
        //右下标
        int r = right;
        //pivot 中轴值
        int pivot = arr[(left + right) / 2];
        //临时变量。作为交换时使用
        int temp = 0;
        //while循环的目的是让比pivot值小的放到左边,比pivot值大的放到右边
        while (l < r) {
            //在pivot的左边一直找,找到大于等于pivot的值,才退出
            while (arr[l] < pivot) {
                l = l + 1;
            }
            //在pivot的右边一直找,找到小于等于pivot的值,才退出
            while (arr[r] > pivot) {
                r = r - 1;
            }
            //如果l >= r,说明pivot左右两边的值,符合左边小于等于pivot,左边大于等于pivot
            if (l >= r) {
                break;
            }
            //交换
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;
            //如果交换完成以后,发现arr[l] = pivot,则需要将r--,前移一步
            if (arr[l] == pivot) {
                r = r - 1;
            }
            //如果交换完成以后,发现arr[r] = pivot,则需要将l++,后移一步
            if (arr[r] == pivot) {
                l = l + 1;
            }
        }
        //如果l == r ,必须执行l++,r--操作,否则会出现栈内存溢出的情况
        if (l == r) {
            l = l + 1;
            r = r - 1;
        }
        //向左递归
        if (left < r) {
            quickSort(arr, left, r);
        }
        //向右递归
        if (right > l) {
            quickSort(arr, l, right);
        }

    }

}

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

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

相关文章

【MySQL系列】Centos安装MySQL

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

10天玩转Python第1天:python基础知识与常用开发工具全面详解

这里写自定义目录标题 1.课程之前1.1 课程介绍1.2 今日内容1.3 Python 介绍[了解]1.4 语言的分类 2 Python 环境配置2.1 Python 解释器的安装2.2 pycharm 的配置安装2.3 路径的选择(建议) 3 使用 pycharm 书写代码3.1 双击打开 pycharm 软件3.2 创建新 项目3.3 配置项目的路径和…

网工内推 | 项目经理专场,最高20K*13薪,软考证书优先

01 Trasen 招聘岗位&#xff1a;大项目经理&#xff08;医疗行业/HIS&#xff09; 职责描述&#xff1a; 1.负责项目按计划完成交付并顺利验收结项&#xff1b; 2.参与项目前期预算、评审、方案设计等&#xff1b; 3.负责具体项目实施&#xff0c;制定项目计划、组织项目资源、…

wvp gb28181 pro 配置https访问

准备工作 必须要有域名。虽然数字证书也有ip证书,但是会很麻烦,多数ca机构验证服务器需要用到80或443端口,也就是必须先备案,所以最好还是使用域名证书。购买域名证书。根据安全级别要求自行配置。单域名(不支持通配符的),阿里云的域名都是可以免费申请的。完成域名到服…

jieba,一个结巴的Python库

微信公众号&#xff1a;愤怒的it男&#xff0c;超多Python技术干货文章。 一、jieba的简介 在自然语言处理任务时&#xff0c;中文文本需要通过分词获得单个的词语&#xff0c;此时一个好的分词工具是非常有必要的。jieba分词是一个开源项目&#xff0c;地址为&#xff1a;git…

Python从入门到精通四:Python循环语句

前言 循环普遍存在于日常生活中&#xff0c;同样&#xff0c;在程序中&#xff0c;循环功能也是至关重要的基础功能。 为什么学习循环语句 循环在程序中同判断一样&#xff0c;也是广泛存在的&#xff0c;是非常多功能实现的基础&#xff1a; while循环的基础语法 学习目标&…

竞赛保研 LSTM的预测算法 - 股票预测 天气预测 房价预测

0 简介 今天学长向大家介绍LSTM基础 基于LSTM的预测算法 - 股票预测 天气预测 房价预测 这是一个较为新颖的竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-senior/postgraduate 1 基于 Ke…

基于Qt的登录页面设计

题目&#xff1a; 完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和…

leetcode 股票DP系列 总结篇

121. 买卖股票的最佳时机 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。 只能进行一次交易 很简单&#xff0c;只需边遍历边记录最小值即可。 class Solution { public:int maxProfit(vector<int>& prices) {int res …

Java:字符流 文件输出 与 读入 方法

Java&#xff1a;字节流 文件输出与读入方法 并 实现文件拷贝 文章目录 字符流FileReaderFileWrite 字符流 字符流底层就是字节流。 字符流 字节流 字符集 特点&#xff1a; 输入流&#xff1a;一次读入一个字节&#xff0c;遇到中文时&#xff0c;一次读多个字节。 输出流…

我的 CSDN 三周年创作纪念日:2020-12-12

本人大叔一枚&#xff0c;自1992年接触电脑&#xff0c;持续了30年的业余电脑发烧爱好者&#xff0c;2022年CSDN博客之星Top58&#xff0c;阿里云社区“乘风者计划”专家博主。自某不知名财校毕业后进入国有大行工作至今&#xff0c;先后任职于某分行信息科技部、电子银行部、金…

六级翻译之印章

好像大房子挺难得 三段式 1Since ancient from now&#xff0c;seals have been a symbol of power and certerfiction of identity.seals not only practical but also is a form of art.Seal is an ancient art combining with manafutuer of crafting and desgin of…

基于SSM的健身房预约系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

2023Python自动化测试5种模型(建议收藏)

1、前言 在自动化测试中&#xff0c;我们往往将自动化脚本都归纳属于哪种框架模型&#xff0c;比如关键字驱动模型等。 本篇将列举实际自动化测试中&#xff0c;Python 自动化测试的五种模型&#xff1a;线性模型、模块化驱动模型、数据驱动模型、关键字驱动模型、行为驱动模…

访问NFS存储及自动挂载

本章主要介绍NFS客户端的使用 创建NFS服务器并通过NFS共享一个目录 在客户端上访问NFS共享的目录 自动挂载的配置和使用 1 访问NFS存储 前面介绍了本地存储&#xff0c;本章就来介绍如何使用网络上的存储设备。NFS即网络文件系统&#xff0c;所实现的是 Linux 和 Linux 之间的…

AI降重软件,AI降重后原创高质量文章

在当今信息爆炸的时代&#xff0c;写作与创作的重要性日益凸显。随着大量内容的涌现&#xff0c;文章降重成为了许多作者和内容创作者的一大问题。本文将专心分享该软件的优势&#xff0c;并为广大用户推荐几款好用的AI降重软件。 AI降重使用场景 AI降重技术利用机器学习算法和…

扔掉xshell,基于 QT 实现一个串口命令行工具(带源码)

背景 xshell 带有支持串口的命令行能力&#xff0c; 可以方便的和下位机用命令进行交互&#xff0c;如下图所示&#xff1a; msh > msh > msh >version\ | / - RT - Thread Operating System/ | \ 3.1.3 build Nov 7 20232006 - 2019 Copyright by rt-thre…

《opencv实用探索·十四》VideoCapture播放视频和视像头调用

1、VideoCapture播放视频 #include <opencv2/opencv.hpp> #include <iostream>using namespace std; using namespace cv;int main() {// 定义相关VideoCapture对象VideoCapture capture;// 打开视频文件capture.open("1.avi");// 判断视频流读取是否正…

聚首引领行业风潮!聚首品牌联动资源价值平台发布会正式启航

2023年12月10日&#xff0c;由杭州建筑装饰学会、浙江聚首联优材料科技有限公司主办&#xff0c;天尚设计集团、公和设计集团、铭扬工程设计集团、地标设计集团、上宸工程设计集团、华坤建筑设计院、广厦建筑设计研究院、上海传承博华建筑规划设计院、航冠工程设计院、浙江鸿能…

控制台打印如来佛图像

代码 System.out.println(" _ooOoo_ \n"" o8888888o \n"" 88 \".\" 88 …