基本思想

已发布:

【算法知识】详解选择冒泡算法

【算法知识】详解选择排序算法

【算法知识】详解插入排序算法

本文的思路是以从小到大为例讲的。
快速排序的基本思想是任取待排序序列的一个元素作为中心元素(可以用第一个,最后一个,也可以是中间任何一个),习惯将其称为pivot,枢轴元素;
将所有比枢轴元素小的放在其左边;
将所有比它大的放在其右边;
形成左右两个子表;
然后对左右两个子表再按照前面的算法进行排序,直到每个子表的元素只剩下一个。

可见快速排序用到了分而治之的思想。
将一个数组分成两个数组的方法为:
先从数组右边找到一个比枢轴元素小的元素,将数组的第一个位置赋值为该元素;
再从数组的左边找到一个比枢轴元素大的元素,将从上面取元素的位置赋值为该值;
依次进行,直到左右相遇,把枢轴元素赋值到相遇位置。

例子

输入数组
arr 为 [39 , 28  , 55 ,  87 , 66 , 3 ,17 ,39*]
为了区别两个相同元素,将最后一个加上 * ;
初始状态如下图:

初始状态

定义一枢轴元素pivot,初始化为第一个元素的值,即39;
查询左边的元素的变量为left,初始值为第一个元素的索引,0;
查询右边的元素的变量为right,初始值为第一个元素的索引,7。
如下图:

初始化

演示第一轮排序过程
从右边开始,从右边找到一个比枢轴元素小的,如果没找到right一直自减1;

第一轮排序状态1

然后把当前left所在元素赋值为该值;
这里right所指元素并没有空,只是为了好演示,设置为空(下同);

第一轮排序状态2

然后从左边开始找一个比枢轴元素pivot大的元素;如果没找到left一直自增1;

第一轮排序状态3

将当前right所指元素设为该值;

第一轮排序状态4

然后从右边找到一个比枢轴元素小的,如果没找到right一直自减1;

第一轮排序状态5

将当前left所指元素设为该值;

第一轮排序状态6

然后从左边开始找一个比枢轴元素pivot大的元素;如果没找到left一直自增1;

第一轮排序状态7

将当前right所指元素设为该值;

第一轮排序状态8

然后从右边找到一个比枢轴元素小的,如果没找到right一直自减1;

第一轮排序状态9

这时left和right相遇了,将枢轴元素赋值给当前位置。

第一轮排序状态10

第一轮排序动态过程:

第一轮排序动态过程

然后将数组分成了

[17,28,3]  与  [66, 87, 55, 39*]两部分;
再对这两部分进行上述环节即可。
反反复复,直到只剩下一个元素。

排序全过程

排序全过程

代码

对每一个数组进行分化的代码如下:
初始化pivot为数组第一个元素;
只要left还小于right就进行循环;
外层循环内部如下:
先从右边找一个比枢轴元素小的元素;
将当前left所指元素赋值为找到的元素;
再从左边找一个比枢轴元素大的元素;
将当前right所指元素赋值为找到的元素;
当left和right相等将枢轴元素赋值在此。
最后返回中间元素的索引。

public static int partition(int[] arr,int left,int right){int pivot = arr[left];while(left < right){while(left<right && arr[right] >= pivot)right--;arr[left] = arr[right];while(left < right && arr[left]<= pivot)left++;arr[right] = arr[left];}arr[left] = pivot;return left;}

快排代码:
第一个是快排的重载,直接传数组;
然后调用另一个重载函数,传数组,left为第一个元素索引0,right为最后一个元素索引数组长度减去1;
主要介绍传三个参数的快排函数:
定义一个将来划分为两个数组的中间元素的索引;
如果left比right小,进行一次划分,将返回来的值赋值给middle;
对left到middle - 1的部分进行一次快排(递归进行);
对middle + 1到right的部分进行一次快排(递归进行)。

public static void quickSort(int[] arr){quickSort(arr,0,arr.length-1);System.out.println(Arrays.toString(arr));}public static void quickSort(int[] arr,int left,int right){int middle;if(left < right){middle = partition(arr,left,right);quickSort(arr,left,middle-1);quickSort(arr,middle+1,right);}}

完整代码:

import java.util.Arrays;public class Solution {public static void main(String[] args) {quickSort(new int[]{39,28,55,87,66,3,17,39});}public static void quickSort(int[] arr){quickSort(arr,0,arr.length-1);System.out.println(Arrays.toString(arr));}public static void quickSort(int[] arr,int left,int right){int middle;if(left < right){middle = partition(arr,left,right);quickSort(arr,left,middle-1);quickSort(arr,middle+1,right);}}public static int partition(int[] arr,int left,int right){int pivot = arr[left];while(left < right){while(left<right && arr[right] >= pivot)right--;arr[left] = arr[right];while(left < right && arr[left]<= pivot)left++;arr[right] = arr[left];}arr[left] = pivot;return left;}
}

时间复杂度

理想的情况:
每次划分所选择的中轴元素恰好将当前序列几乎等分,经过趟划分,便可以排序完毕。这样,所以理想状态下整个算法的时间复杂度为。
最坏的情况是,每次所选的中间数是当前序列中的最值元素,这时每次划分的两个子表一个长度是0,一个是当前数组长度减去1。这样的话,长度为n的数组需要经过n趟划分,这时的时间复杂度为;
为改善最坏情况下的时间性能,可以在最枢轴元素的原则中进行优化,选第一个元素,最后一个元素,中间元素中的中位数即可。
这时,快速排序的时间复杂度即为。

稳定性

如下面的数组
相同元素用 *  标出 [ 2 , 3  , 1, 1* ]
第一次排序为
[1* , 1, 2, 3]
第二次为
[1* , 1 , 2 , 3] 相对顺序发生了变化,所以是不稳定的。


往期精彩回顾适合初学者入门人工智能的路线及资料下载机器学习在线手册深度学习在线手册AI基础下载(pdf更新到25集)本站qq群1003271085,加入微信群请回复“加群”获取一折本站知识星球优惠券,复制链接直接打开:https://t.zsxq.com/yFQV7am喜欢文章,点个在看

【算法知识】详解快速排序算法相关推荐

  1. 快速排序_详解快速排序算法

    快速排序(Quicksort),计算机科学词汇,适用领域Pascal,c++等语言,是对冒泡排序算法的一种改进. 快速排序的排序流程 快速排序算法通过多次比较和交换来实现排序,其排序流程如下: (1) ...

  2. xgboost算法_详解xgboost算法的样本不平衡问题

    XGBoost官方文档对参数scale_pos_weight的定义: 翻译: 调节正负样本权重的平衡 ,常用来处理不平衡的正负样本数据 . 典型值算法: scale_pos_weight = 负样本总 ...

  3. 什么是DES算法,详解DES算法的基本原理

    DES算法是应用最为广泛的对称加密算法.它主要应用在计算机网络通信.电子资金传送系统.保护用户文件,此外,DES还可用于计算机用户识别系统中.那么,具体什么是DES算法,DES算法的基本原理是什么,本 ...

  4. 【算法知识】详解堆排序算法

    点击蓝色字关注我们! 什么是堆 「堆」首先是一个完全二叉树,「堆」分为「大顶堆」和「小顶堆」: 「大顶堆」 : 每个节点的值大于或等于其左右孩子节点的值,称为大顶堆. 「小顶堆」同理就是每个节点的值小 ...

  5. 【算法知识】详解基数排序算法

    已发布: [算法知识]详解选择冒泡算法 [算法知识]详解选择排序算法 [算法知识]详解插入排序算法 [算法知识]详解快速排序算法 [算法知识]详解归并排序算法 基本思想 基数排序的思想是将整数按位数切 ...

  6. 【算法知识】详解归并排序算法

    已发布: [算法知识]详解选择冒泡算法 [算法知识]详解选择排序算法 [算法知识]详解插入排序算法 [算法知识]详解快速排序算法 基本思想 归并排序的基本思想是: 先将序列一次次分成子序列,直到子序列 ...

  7. 游戏洗牌算法——常用+详解最优Knuth_Durstenfeld算法

    目录 前言 基于Unity的洗牌算法代码实现 内容 抽牌洗牌 原理 复杂度 优缺点 Fisher_Yates算法 原理 复杂度 代码实现 优缺点 Knuth_Durstenfeld算法(最佳洗牌算法) ...

  8. js排序算法详解-快速排序

    全栈工程师开发手册 (作者:栾鹏) js系列教程5-数据结构和算法全解 js排序算法详解-快速排序 既然是快速排序,那顾名思义一定很快,快的连小编都被懵逼了好几圈!建议先不要看动图,先看第一种写法: ...

  9. python 快速排序_小白入门知识详解:Python实现快速排序的方法(含实例代码)...

    前言: 今天为大家带来的内容是:小白入门知识详解:Python实现快速排序的方法(含实例代码)希望通过本文的内容能够对各位有所帮助,喜欢的话记得点赞转发收藏不迷路哦!!! 提示: 这篇文章主要介绍了P ...

最新文章

  1. 剑指offer 40.最小的 K 个数 python代码
  2. PV(page view)
  3. Linux系统配置交换分区
  4. 多进程客户端-服务器模型
  5. SDN中的Heavy-Hitter测量文献阅读
  6. ansible(自动化运维上)——ansible部署,添加主机组,连通性测试
  7. Prism源代码解析(IRegionManager)
  8. 不用“背”单词,1个方法牢记7000单词:我是如何做到的?
  9. [剑指offer]面试题第[53-1]题[JAVA][在排序数组中查找数字-1][二分法][暴力法]
  10. 学习.NET是因为热爱 or 兴趣 or 挣钱?
  11. 如何在Linux中将用户添加到组
  12. 云图说|不要小看不起眼的日志,“小日志,大作用”
  13. 10句编程箴言 每个程序员都应该知道
  14. 程序人生:半路转行再来学软件测试,能够成为大牛吗?
  15. 嘻哈 软件技术知识与项目管理知识
  16. C/C++[codeup 1808]字符串查找删除
  17. cc2540 android,手机APP通过CC2541蓝牙模块来控制LED等,附安卓APP源码
  18. plt图像保存到pdf文件
  19. 如何将已有图片做成透明水印_如何给图片制作透明水印
  20. 记一次使用screw 生成MySQL数据库文档

热门文章

  1. 几个不错的自己到的少的游戏站
  2. Silverlight 2学习笔记一:初识Silverlight
  3. 刷新后控制TAB键到下一个控件
  4. The Road to SDN: An Intellectual History of Programmable Networks
  5. 复合数据类型,英文词频统计
  6. Hihocoder-1135-Magic Box
  7. 详细解读Jquery各Ajax函数:$.get(),$.post(),$.ajax(),$.getJSON()
  8. Flash的层叠顺序问题(z-index)
  9. s3c2410开发环境建立
  10. 这几个GraphPad Prism使用的小技巧让你绘图效率直接翻倍