在进入这个话题之前大家可以想想,如果给你一个无序数组,要你处理成一个有序数组,你会怎么做?
可能是双循环的冒泡排序,可能拆开成多个子集合的再合并的希尔排序,排序算法很多,而现在要介绍的是另一种排序方法
快速排序

快速排序的基本思想

快速排序基本思想就是分而治之,分而治之是什么意思不清楚?别急我们现在就来探索一下。

分而治之

我们只需要明白,分而治之就是把一个大的问题分成多个小问题来解决的一种思路,最常用的就是递归了。

如何把分而治之应用在排序上?

在讲这个的时候,举个栗子或许会更加容易理解些。(如不想看或已了解可跳过,实现代码在最后)

大家上学的时候应该都经历过这样的一种场景:排座位前的按身高排队。老师会让整个班级的人去门外走廊上排成一队,但是同学比较调皮不按身高从低到高依次排列,那么这个时候就需要老师来把队伍整理成有序的了。

加入老师以这样的方式来排序:老师先从队伍中随便找出一个同学,我们称为A。然后告诉同学们:比A的站左边,比A的站右边。那么这样一来,左边的都是比这个同学矮的,右边都是比这个同学高的。类似于以下这样

所以剩下的任务就是把A 左边和右边的同学 分为两队重复上述方式排序好。
这个时候你是不是想到了,那不就是递归吗?没错,就是递归。

如何实现快速排序

思路有了,现在就要把思路变成代码,并且实现了。我们先看看上述有几个过程。

第一步:找出一个同学A,利用他作为标准,把所有同学分成两组,一组在左比他矮,一组在右比他高。

第二步:把除A以外的其他同学,分为两组。重复上述过程,直到整个队伍,排序完成,变成有序的队伍。

好的,我们现在知道大概的步骤了,想想怎么实现吧。先看第一步,在第一步中我们做了,两个操作。
1、找出分队标准。先找出一个同学,我们称之为A,用作其他同学比较的标准。这个简单,因为队伍是无序的,我们可以取队伍最前面的人作为标准。
2、比较分队,找到A应该呆在的位置,并且以A为中点分队。将所有同学与A比较,将队伍以A为中心分为两队。我们常规的思路可能是,一个一个比较,比A矮的站左边,比A高的站右边。但是为了避免这种自由交换过程中学生们互相聊天、玩闹,打扰到楼下其他班级正在上课的同学,所以交换位置由老师主持,每次交换两个人的位置。老师的具体做法如下:先从队伍的末尾往前,找出一个比A矮的,再从队伍最前往后找出一个比他高的,并且记录这两人的位置,然后交换这两人的位置。

重复此操作,直到遇到这样的一种情况:假设从末尾开始找的比A矮的同学为B,从前往后找到的比A高的同学为C。因为B是从后往前找的,那么B的位置大概率是在C的后面,当B在C的后面时,正好交换两人的位置。当找到的B在C前面时呢?
我们看这个图:

这种情况就是交换B、C的位置即可
但是怎么确定A应该在队伍里的何处呢?当找到的B(从末尾往前找比A矮的)在C(从前往后找比A高的)前面时,那么A的位置是不是找到了,如下图

那么这个时候,A应该与谁交换位置,才能使得队伍左边比A矮,队伍右边比A高呢?
我们回头看看老师的做法:先从队伍的末尾往前,找出一个比A矮的–B同学,再从队伍最前往后找出一个比他高的–C同学,并且记录这两人的位置,然后交换这两人的位置。

也就意味着,B的身高是比A矮的,C的身高是比A高的,我们要做的是比A矮的站左边,比A高的站右边,我们毫无疑问是交换B和A。这样的话,C不动,比A高,B换到第一位比A矮,这样就队伍以A为中心分开了。如果交换C呢?因为C比A高,换到左边,是不是不符合排队从矮到高的要求?

至此,整个队伍就被分成了以A为中心两队。

再把比A矮的同学和比A高的同学,按以上方法,排序就可以了。现在我们假如比A矮的同学有5人,比A高的同学有5人。那么现在需要先对左边5人继续排序,那么我们再用上面的方法,5人队伍分为两队,左边两人队,右边也是两人队伍以及作为标准在中间的同学。然后再分,再把左边的两人队伍分为一人队伍和作为标准的同学。
如下图()只分析左侧


对两人队伍的分析,有两种情况,一种是剩下的那位在作为标准值的同学左侧,另一种是在他的右侧。我们假设为在左侧,如下图

那么当以标准值的同学一侧的队伍只有一个人时,这支队伍就排好序了。

如果把作为标准的同学拿出来,你就会发现,作为标准的同学身高从前往后是有序的。你如果把整个分队过程画完,你就会发现,一人队伍和作为标准的同学,就是一个有序的队伍了。

以上就是整个快速排序的思路了。
伪代码代码见下图

public static void quickSort(int nums[] , int left , int right) {//方法是否已达出口//找基准值 把数组分为左右两部分//交换基准值与找到的右侧的位置 右侧值比基准值小//对左右半边执行同样的操作 } 

具体实现如下:

/*** @param nums* 数组* @param left* 左侧边界* @param right* 右侧边界* @return*/public static void quickSort(int nums[] , int left , int right) {//方法出口if(left >= right) {return;}//baseValue-基准值//temp-用于交换位置的临时变量//i-从左侧开始寻找大于基准值的下标//j-从右侧开始寻找小于基准值的小于基准值的下标int i,j,baseValue,temp;baseValue = nums[left];//基准值设为左侧第一位i = left; j = right;//找出基准值 把数组分为左右两部分while(i < j) {//从末尾往前找出小于基准值的数 i < j 保证 i在j的左侧while(nums[j] >= baseValue && i < j) {j--;}//从起始位置往右找出大于基准值的数while(nums[i] <= baseValue && i < j) {i++;}//若i<j交换左右值的位置if(i < j) {temp = nums[i];nums[i] = nums[j];nums[j] = temp;}}//交换基准值与找到的右侧的位置 右侧值比基准值小temp = nums[left];nums[left] = nums[j];nums[j] = temp;//对左右半边执行同样的操作 需要使用左右侧边界的值quickSort(nums , left , j - 1);//左侧排序quickSort(nums , j + 1 , right);//右侧排序}public static void main(String[] args) {//无序数组int nums[] = {9,18,4,27,3,21,15,18,34,5,14};//倒序数组int nums2[] = {10,9,8,7,6,5,4,3,2,1};//同值数组int nums3[] = {3,3,3,3,3,3,3,3,3,3};//打印排序前数组System.out.println("无序数组排序前");for(int i = 0; i <= nums.length - 1; i++) {if(i != nums.length - 1)System.out.print(nums[i] + ", ");elseSystem.out.println(nums[i]);}//快速排序quickSort(nums, 0, nums.length - 1 );//打印排序后数组System.out.println("无序数组排序后");for(int i = 0; i <= nums.length - 1; i++) {if(i != nums.length - 1)System.out.print(nums[i] + ", ");elseSystem.out.println(nums[i]);}//打印排序前数组System.out.println("倒序数组排序前");for(int i = 0; i <= nums2.length - 1; i++) {if(i != nums2.length - 1)System.out.print(nums2[i] + ", ");elseSystem.out.println(nums2[i]);}//快速排序quickSort(nums2, 0, nums2.length - 1 );//打印排序后数组System.out.println("倒序数组排序后");for(int i = 0; i <= nums2.length - 1; i++) {if(i != nums2.length - 1)System.out.print(nums2[i] + ", ");elseSystem.out.println(nums2[i]);}System.out.println("同值数组排序前");for(int i = 0; i <= nums3.length - 1; i++) {if(i != nums3.length - 1)System.out.print(nums3[i] + ", ");elseSystem.out.println(nums3[i]);}//快速排序quickSort(nums3, 0, nums3.length - 1 );//打印排序后数组System.out.println("同值数组排序后");for(int i = 0; i <= nums3.length - 1; i++) {if(i != nums3.length - 1)System.out.print(nums3[i] + ", ");elseSystem.out.println(nums3[i]);}}

当然以上代码还可对输入的数组做一下非空判断,对于输入空数组的情况直接结束循环。

Java的快速排序算法详解相关推荐

  1. 快速排序算法详解(原理,时间复杂度,实现代码)

    快速排序算法详解(原理.实现和时间复杂度) 快速排序是对冒泡排序的一种改进,由 C.A.R.Hoare(Charles Antony Richard Hoare,东尼·霍尔)在 1962 年提出. 快 ...

  2. 十大经典排序算法-快速排序算法详解

    十大经典排序算法 十大经典排序算法-冒泡排序算法详解 十大经典排序算法-选择排序算法详解 十大经典排序算法-插入排序算法详解 十大经典排序算法-希尔排序算法详解 十大经典排序算法-快速排序算法详解 十 ...

  3. Java垃圾回收算法详解

    1 概述 在前一篇文章中讲到了Java虚拟机的基础知识和运行时数据区的划分,在运行时数据区的划分中,可分为线程共享区域和线程私有区域,而Java的垃圾回收就发生在线程共享区域中,更直观的说法就是Jav ...

  4. 经典排序算法(2)——快速排序算法详解

    快速排序(Quick Sort)也是一种典型的交换排序算法,通过交换数据元素的位置进行排序. 一.算法基本思想 (1)基本思想 快速排序的基本思想就是:通过一趟排序将要排序的数据分割成独立的两部分,其 ...

  5. 使用 Java 实现快速排序(详解)

    一.概述 最近在看一些面试题,发现很多面试过程中都会要求手写快速排序,查阅一些博客发现别人写的并不是特别清楚而且也很难记住,所以为了更好的掌握这个算法,所以在这篇文章中,将自己的学习过程记录下来,你将 ...

  6. Java快排算法详解

    快排算法底层基本思想: 先取出数列中的第一个数作为基准数. 将数列中比基准数大的数全部放在他的右边,比基准数小的数全部放在它的左边. 然后在对左右两部分重复第二步,直到各个区间只有一个数. 具体Jav ...

  7. 快速排序 算法 详解 及 深度优化

    下面简介经典算法  快速排序算法 实现及优化. (欢迎大家指点,继续提出优化的方法,共同提高) 基本思想:(以按从小到大排序为例说明)通过多次的排序,每次的排序均将要排序的数组分为两部分,前一部分均比 ...

  8. des算法s盒java实现_DES算法详解

    本文主要介绍了DES算法的步骤,包括IP置换.密钥置换.E扩展置换.S盒代替.P盒置换和末置换. 1.DES算法简介 DES算法为密码体制中的对称密码体制,又被称为美国数据加密标准. DES是一个分组 ...

  9. 排序算法,最全的10大排序算法详解(Sort Algorithm)

    文章目录 排序算法,最全的10大排序算法详解(Sort Algorithm) 排序算法分类 排序算法稳定性 时间复杂度(time complexity) 1#时间复杂度的意义 2#基本操作执行次数 如 ...

最新文章

  1. PIC单片机入门_异步通讯模式详解
  2. 使用requests请求网页时,返回的页面信息有时是乱码,如下代码
  3. 4个强大的Linux服务器监控工具[转]
  4. echarts 有引导线和内部文字_上进青年研习社丨设计入门02:平面设计之平面构成中的线...
  5. uniapp---为什么使用uniapp_以及uniapp开发的app展示_使用hbuilderx简单搭建一个uniapp_一次开发_小程序_Android_IOS_快应用通用工作笔记002
  6. 【LoadRunner技术讲座8】LoadRunner函数中的几个陷阱
  7. iOS原生APP和H5交互-delegate和第三方
  8. 设计模式学习笔记(二十:享元模式)
  9. 鸿蒙生态发布会,新日XC3亮相华为鸿蒙生态大会,这场合作值得期待!
  10. 【转】Python中操作mysql的pymysql模块详解
  11. ubuntu 16.04 gogs git 环境搭建
  12. 基于python的数据管理系统的设计_基于Python的自然语言数据处理系统的设计与实现...
  13. 4g网卡MF831移植到smart210
  14. 智能的未来关键在于发现新的逻辑体系
  15. @RunWith的使用
  16. 解决影驰固态硬盘SSD卡顿
  17. VS快捷键,常用加粗
  18. 2022年Behance高清大图免费下载技术分享。WIN和MAC电脑通用,官方靠谱小工具。
  19. 【Eigen】【Eigen实践】【Eigen的使用学习记录】
  20. Delphi图像处理 -- 图像合成

热门文章

  1. B003 - 基于51单片机的蓝牙交通灯车流量控制系统
  2. python程序员可以做到多少岁_程序员可以做到80岁吗?
  3. 数字逻辑:寄存器与计数器
  4. IDEA单个文件夹自动折叠的问题
  5. Java线程模仿电影院买票
  6. 结构化电子病历的特点及优势
  7. 智能家居硬件小制作(含源码)《手势识别控制器》基于PAJ7620手势模块、L298N驱动板、arduino
  8. AVFoundation框架理论+实战一(文本语音转换)
  9. 你的城市撒币了吗?Python分析各城市消费券发放数据
  10. matlab制作彩色圆盘