快速排序

目录

什么是快速排序:

图解:

递归法:

 方法一(Hoare法):

  代码实现:

        思路分析:

       方法二(挖坑法):

        代码实现:

        思路分析:

        非递归法:

        图解:

        代码实现:

        思路分析:

        快速排序是不稳定的。


什么是快速排序:

        任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

图解:

        

         假设 0 下标的数字 3 作为我们的基准值,先看上图的left 和 right ,他们一开始是在start 和 end 的位置。

        在走的过程中,right 先走,直到遇到比 3 小的数字停下来,再到 left 走,直到遇到比 3 大的数字停下来;然后交换 此时 left 下标 和 right 下标 的数字,然后不断重复此过程,直到left 与 right 相遇停止;再把最后left 和 right 相遇的 下标位置 与 我们设定的基准值 3 交换;这样就保证了此时的left 位置的下标的左边都是比他小的,右边都是比他大的。也可以说此时的left 下标的数据已经有序了。(用 par 记录left 和 right相遇的位置)

        然后,再看此图:

        

         因为使用了 par 记录了 left 和 righjt 相遇的的位置,那么下次划分 一段数据左边则 使用 start 和 par - 1 作为一段新的数据的 left 和 right ,右边 使用 par + 1 和 end 作为一段新的数据的 left 和 right ,不断细分排序重复下去,直到start 与 end 相遇停止划分;看上图绿色椭圆圈出来的start ,那是在 1 下标右边走划分出来的一段,此时start 大于了 end ,也算一种停止划分条件。

        所以,停止划分的条件是 start >= end

递归法:

 方法一(Hoare法):

  代码实现:
public static void quickSortHoare(int[] arr) {
        quick(arr,0,arr.length - 1);
    }

    private static void quick(int[] arr, int start, int end) {
        if(start >= end) {
            return;
        }

        int par = parrtion(arr,start,end);

        //往左走
        quick(arr,start,par - 1);

        //往右走
        quick(arr,par + 1,end);

    }

    private static int parrtion(int[] arr, int left, int right) {

        int i = left;
        int ret = arr[left];

        while(left < right) {
            while(left < right && arr[right] >= ret) {
                right--;
            }
            while(left < right && arr[left] <= ret) {
                left++;
            }
            //交换
            swap(arr,left,right);
        }
        //交换
        swap(arr,i,left);

        return left;
    }

    private static void swap(int[] arr,int i,int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
        思路分析:

        结合上面我们分析的图解,有个要注意的是 parrtion 方法里 的 left < right && arr[right] >= ret 和 left < right && arr[left] <= ret 这两个的循环条件,前提都要加上 left < right ,因为如果 对于一段已经有序的数据,假设我们使用对一个最小的数据作为基准值,第一个 arr[right] >= ret 循环 判断条件会一直让 right --,如果没有left < right 作为前提条件,会导致 right 越界。

        

       方法二(挖坑法):

        代码实现:
 public static void quickSort2(int[] arr) {
        quick(arr,0,arr.length - 1);
    }

    private static void quick2(int[] arr, int start, int end) {
        if(start >= end) {
            return;
        }

        int par = parrtion2(arr,start,end);

        //往左走
        quick2(arr,start,par - 1);

        //往右走
        quick2(arr,par + 1,end);

    }

    private static int parrtion2(int[] arr, int left, int right) {

        int ret = arr[left];

        while(left < right) {
            while(left < right && arr[right] >= ret) {
                right--;
            }

            arr[left] = arr[right];

            while(left < right && arr[left] <= ret) {
                left++;
            }

            arr[right] = arr[left];

        }
        arr[left] = ret;

        return left;
    }
    private static void swap(int[] arr,int i,int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
        思路分析

        挖坑法 与 Hoare 法思路很相像,不同的是;

        挖坑法 是把 right 找到比 基准值 小的时候,把此时 的 right 下标的值给到 left 下标;left 找到比 基准值 大的时候,把此时 的 left 下标的值给到 right 下标。

        最后,由于一开始使用了 ret 存储了基准值,所以当 left 与 right 相遇时把 ret 给到 left 下标的位置。

        

        非递归法:

        图解:

         

        快速排序非递归的方法我们借助了一个栈,用来存放数据的下标;

        先把一段数据的 left 给到 栈里,再把 right 给到 栈里,然后排完一段序后,得到 par ,再把一段新的数据的 left 和 right 给到 栈里。

        要注意,当:

        

         这是分出来的一段数据,当par右边只剩一个元素时,那么右边剩下的一个元素是有序的,par 左边同理。

        代码实现

public static void quickSortNor(int[] arr) {
        int left = 0;
        int right = arr.length - 1;
        int par = parrtion3(arr,left,right);

        Stack<Integer> stack = new Stack<>();

        //左边有两个元素及以上
        if(left + 1 < par) {
            stack.push(left);
            stack.push(par - 1);
        }

        //右边有两个元素及以上
        if(par < right - 1) {
            stack.push(par + 1);
            stack.push(right);
        }

        while(!stack.isEmpty()) {
             right = stack.pop();
             left = stack.pop();

             par = parrtion3(arr,left,right);

            //左边有两个元素及以上
            if(left + 1 < par) {
                stack.push(left);
                stack.push(par - 1);
            }

            //右边有两个元素及以上
            if(par < right - 1) {
                stack.push(par + 1);
                stack.push(right);
            }
        }
    }

    private static int parrtion3(int[] arr, int left, int right) {

        int ret = arr[left];

        while(left < right) {
            while(left < right && arr[right] >= ret) {
                right--;
            }

            arr[left] = arr[right];

            while(left < right && arr[left] <= ret) {
                left++;
            }

            arr[right] = arr[left];

        }
        arr[left] = ret;

        return left;
    }

        思路分析

        结合上面的图解,一开始在循环外,我们排了一次序,得到了 par ,再把对应的 left 和 right 给到栈里。

        当栈不为空时,栈弹出的第一个元素作为相应一段数据 right ,下一个是对应的 left ,原因是我们放入栈时是先 left 再 right;再对其排序后得到新的 par ,再结合图解分析。直到栈为空时结束。

        

        快速排序是不稳定的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络安全尹毅 《网络安全》

一 网络安全基本概念 1.网络安全定义 安全在字典中的定义是为了防范间谍活动或蓄意破坏、犯罪、攻击而采取的措施。网络安全就是为了防范计算机网络硬件、软件、数据被偶然或蓄意破坏、篡改、窃听、假冒、泄露、非法访问以及保护网络系统持续有效工作的措施总和。网络安全保护…

6.appender

文章目录 一、前言二、源码解析AppenderUnsynchronizedAppenderBaseOutputStreamAppenderConsoleAppenderFileAppenderRollingFileAppenderFileNamePattern 三、总结 一、前言 前一篇文章介绍了appender、conversionRule、root和logger节点的解析, 为的是为本篇详细介绍它们的…

P9584 「MXOI Round 1」城市

题目描述 小 C 是 F 国的总统&#xff0c;尽管这个国家仅存在于网络游戏中&#xff0c;但他确实是这个国家的总统。 F 国由 n 个城市构成&#xff0c;这 n 个城市之间由 n−1 条双向道路互相连接。保证从任意一个城市出发&#xff0c;都能通过这 n−1 条双向道路&#xff0c;…

什么是Docker多架构容器镜像

什么是Docker多架构容器镜像 在 Docker 中&#xff0c;同一个 Docker 镜像可以在不同的平台上运行&#xff0c;例如在 x86、ARM、PowerPC 等不同的 CPU 架构上。 为了支持这种多平台的镜像构建和管理&#xff0c;Docker 在 17.06 版本时引入了 Manifest 的概念&#xff0c;在…

Baklib知识中台构建企业智能运营核心架构

内容概要 在数字化转型的浪潮中&#xff0c;企业对于知识的系统化管理需求日益迫切。Baklib作为新一代的知识中台&#xff0c;通过构建智能运营核心架构&#xff0c;为企业提供了一套从知识汇聚到场景化落地的完整解决方案。其核心价值在于将分散的知识资源整合为统一的资产池…

深度学习机器学习:常用激活函数(activation function)详解

目录 Sigmoid Function ReLU&#xff08;Rectified Linear Unit&#xff09; LeakyReLU&#xff08;Leaky Rectified Linear Unit&#xff09; ClippedReLU&#xff08;Clipped Rectified Linear Unit&#xff09; PRelu&#xff08;Parametric ReLU&#xff09; Tanh&am…

【面试】网络安全常问150道面试题

1&#xff0c;拿到一个待测网站&#xff0c;你觉得应该先做什么&#xff1f; 信息收集&#xff1a; 服务器相关---&#xff1a;## 系统版本&#xff0c;真实IP&#xff0c;开放端口&#xff0c;使用的中间件 指纹信息---## 有无cdn加速&#xff0c;dns解析记录&#xff0c;是不…

【Linux】--- 基础开发工具之yum/apt、vim、gcc/g++的使用

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; Linux网络编程 本篇博客我们来认识一下Linux中的一些基础开发工具 --- yum,vim,gcc/g。 &#x1f3e0; yum &#x1f3b8; 什么是yum 当用户想下载软…

物联网平台-分布式的设备接入与管理系统

乐吾乐物联网平台是由乐吾乐自主研发的一款分布式的设备接入与管理系统&#xff0c;专为满足不断增长的设备接入和数据处理需求而设计。平台集数据采集、分析、监控、告警和通知等功能于一体&#xff0c;并融合了乐吾乐大屏可视化和乐吾乐3D数字孪生技术&#xff0c;帮助用户快…

Day65_20250213图论part9_dijkstra(堆优化版)|Bellman_ford算法精讲

Day65_20250213图论part9_dijkstra(堆优化版)|Bellman_ford算法精讲 dijkstra(堆优化版) 题目 https://www.programmercarl.com/kamacoder/0047.%E5%8F%82%E4%BC%9Adijkstra%E5%A0%86.html 小明参加科学大会 思路 思路 朴素版的dijkstra&#xff0c;时间复杂度为O(n^2)&am…

动手实现自己的 JVM——Go!(ch01)

动手实现自己的 JVM——Go&#xff01;&#xff08;ch01&#xff09; 参考张秀宏老师的《自己动手写java虚拟机》 为什么需要命令行 在 JMV 中&#xff0c;要运行一个 Java 文件&#xff08;字节码&#xff09;&#xff0c;首先需要找到这个文件。那么&#xff0c;如何找到文件…

IIS部署netcore程序后,出现500.30错误解决方案之一

netcore程序部署到IIS后一直出现错误&#xff0c;访问首页后会跳转到登录页地址&#xff0c;然后看到如下错误 HTTP Error 500.30 - ANCM In-Process Start Failure Common solutions to this issue: The application failed to start The application started but then stopp…

将Docker容器打包成镜像提交

前言 Docker 是一个开源软件&#xff0c;也是一个开放平台&#xff0c;用于开发应用、交付&#xff08;shipping&#xff09;应用、运行应用。 Docker允许用户将基础设施&#xff08;Infrastructure&#xff09;中的应用单独分割出来&#xff0c;形成更小的颗粒&#xff08;容…

【设计模式】【行为型模式】命令模式(Command)

&#x1f44b;hi&#xff0c;我不是一名外包公司的员工&#xff0c;也不会偷吃茶水间的零食&#xff0c;我的梦想是能写高端CRUD &#x1f525; 2025本人正在沉淀中… 博客更新速度 &#x1f44d; 欢迎点赞、收藏、关注&#xff0c;跟上我的更新节奏 &#x1f3b5; 当你的天空突…

【DDD系列-3】DDD战术设计实践分享

DDD 战术设计概念​ ​ ​​ TMF2 中的概念&#xff1a;​ 领域能力&#xff1a;​ 扩展点&#xff1a;​ DDD 战术设计使用场景​ 复杂业务场景​ 复杂来源面对的需求方更加多样化。​ 1 相同场景不同垂直业务方的需求&#xff08;1688&#xff0c;淘宝&#xff0c;天…

基于单片机的仓库安防系统(论文+源码)

2.1 需求分析 仓库由于存有大量物品&#xff0c;因此对仓库的监控非常重要&#xff0c;目前仓库已经普遍装有安防系统&#xff0c;以保证仓库的安全&#xff0c;本次基于单片机的仓库安防系统设计&#xff0c;在功能上设计如下&#xff1a; 用户可通过IC卡进入仓库&#xff1…

使用 AutoMQ 和 Tinybird 分析用户网购行为

前言 在当前竞争激烈的市场环境中&#xff0c;数据分析已成为企业实现差异化和精准营销的关键。通过分析用户行为数据&#xff0c;企业能够深入了解用户的习惯、偏好和行为模式&#xff0c;从而更精准地定位目标市场&#xff0c;制定个性化营销策略&#xff0c;并提供定制化推…

小米 R3G 路由器刷机教程(Pandavan)

小米 R3G 路由器刷机教程&#xff08;Pandavan&#xff09; 一、前言 小米 R3G 路由器以其高性价比和稳定的性能备受用户青睐。然而&#xff0c;原厂固件的功能相对有限&#xff0c;难以满足高级用户的个性化需求。刷机不仅可以解锁路由器的潜能&#xff0c;还能通过第三方固…

Python数据可视化 - Matplotlib教程

文章目录 前言一、Matplotlib简介及安装1. Matplotlib简介2. 安装Matplotlib 二、Matplotlib Pyplot1. Pyplot介绍2. Pyplot中方法介绍2.1 创建和管理图形2.2 绘制图形2.3 设置图形属性2.4 保存和展示 三、Matplotlib绘图标记1. 介绍2. 基本用法3. 标记大小与颜色4. 标记样式列…

DeepSeek 与网络安全:AI 驱动的智能防御

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 随着人工智能&#xff08;AI&#xff09;的快速发展&#xff0c;深度学习技术正渗透到多个领域&#xff0c;从医疗诊断到…