在网上搜索算法的博客,发现一个比较悲剧的现象非常普遍:

  • 原理讲不清,混乱
  • 啰嗦
  • 图和文对不上
  • 不可用,甚至代码还出错

为了不误人子弟耽误时间,推荐看一些靠谱的资源,如【啊哈!算法】系列:

https://www.cnblogs.com/ahalei/p/3568434.html

他是C语言实现,其实都是一样的。

我总结一个清晰不罗嗦版:

原理:

快速排序使用分而治之策略。下面描述递归步骤:

选择一个pivot支点值(在啊哈算法中叫“基准值”)。我们将中间元素的值作为支点值,但是它也可以是任何值,甚至它可以不存在于数组中。

第一次排序:

  • 小于支点值的所有元素都到支点值的左侧
  • 而大于支点值的所有元素都到支点值的右侧
  • 与支点值相等的值保留。

递归,再次以支点两侧排序:对两部分进行排序,将快速排序算法递归地应用到左右部分。数组可以以不相等数量的部分划分。

算法要点:

  • 有两个索引i和j,在算法的第一次排序,i 指向数组中的第一个元素,j 指向最后一个元素。
  • i向前移动,直到找到一个值大于或等于支点值的元素。
  • 索引j向后移动,直到找到一个值小于或等于支点值的元素。
  • 如果i小于j,则它们被交换,然后进入下一个位置(i + 1),j进到前一个(j - 1)。
  • 当大于j时,算法停止。

第一次排序的说明:

在第一轮排序之后,会进入左右的递归。依次类推。

复杂度分析

排序方法 时间复杂度 空间复杂度 稳定性 复杂性
平均情况 最坏情况 最好情况
快速排序 O(nlog2n) O(n2) O(nlog2n) O(log2n) 不稳定 较复杂

用JAVA实现(真实可用):

  1. package Sort;
  2.  
  3. public class QuickSort {
  4.  
  5. public static void main(String[] args) {
  6.  
  7. int arr[] = {1, 12, 5, 26, 7, 14, 3, 7, 2};
  8. int n = arr.length;
  9.  
  10. QuickSort ob = new QuickSort();
  11. ob.quickSort(arr, 0, n-1);
  12. //ob.sort(arr, 0, n-1);
  13.  
  14. System.out.println("快速排序结果:");
  15. printArray(arr);
  16. }
  17.  
  18. int partition(int arr[], int left, int right){
  19.  
  20. int i = left, j = right;
  21. int tmp;
  22. int pivot = arr[(left + right) / 2];
  23. System.out.println("pivot="+pivot+"; left="+left+"; right="+right);
  24.  
  25. while (i <= j) {
  26.  
  27. while (arr[i] < pivot){
  28. System.out.println("跳过,i="+i+"; arr[i]="+arr[i]+", pivot="+pivot);
  29. i++;
  30. }
  31.  
  32. while (arr[j] > pivot){
  33. System.out.println("跳过,j="+j+"; arr[j]="+arr[j]+", pivot="+pivot);
  34. j--;
  35. }
  36.  
  37. if (i <= j) {
  38. System.out.println("交换前,i="+i+", j="+j+"; arr[i]="+arr[i]+", arr[j]="+arr[j]);
  39.  
  40. tmp = arr[i];
  41. arr[i] = arr[j];
  42. arr[j] = tmp;
  43.  
  44. System.out.println("交换后,i="+i+", j="+j+"; arr[i]="+arr[i]+", arr[j]="+arr[j]);
  45. System.out.println("---");
  46.  
  47. i++;
  48. j--;
  49.  
  50. }
  51. };
  52.  
  53. return i;
  54. }
  55.  
  56. void quickSort(int arr[], int left, int right) {
  57.  
  58. int index = partition(arr, left, right);
  59. if (left < index - 1){
  60. System.out.println("递归 左侧,left="+left+", index="+index);
  61. quickSort(arr, left, index - 1);
  62. }
  63.  
  64. if (index < right){
  65. System.out.println("递归右侧,right="+right+", index="+index);
  66. quickSort(arr, index, right);
  67. }
  68. }
  69.  
  70. static void printArray(int arr[])
  71. {
  72. int n = arr.length;
  73. for (int i=0; i<n; ++i)
  74. System.out.print(arr[i]+" ");
  75. System.out.println();
  76. }
  77.  
  78. //另一种简洁写法
  79. int partition1(int arr[], int low, int high)
  80. {
  81. int pivot = arr[high];
  82. int i = (low-1);
  83. for (int j=low; j<high; j++)
  84. {
  85.  
  86. if (arr[j] <= pivot)
  87. {
  88. i++;
  89.  
  90. int temp = arr[i];
  91. arr[i] = arr[j];
  92. arr[j] = temp;
  93.  
  94. }
  95. }
  96.  
  97. int temp = arr[i+1];
  98. arr[i+1] = arr[high];
  99. arr[high] = temp;
  100.  
  101. return i+1;
  102. }
  103.  
  104. void sort(int arr[], int low, int high)
  105. {
  106. if (low < high)
  107. {
  108. int pi = partition1(arr, low, high);
  109.  
  110. sort(arr, low, pi-1);
  111. sort(arr, pi+1, high);
  112. }
  113. }
  114. }

调试信息:

  1. pivot=7; left=0; right=8
  2. 跳过,i=0; arr[i]=1, pivot=7
  3. 交换前,i=1, j=8; arr[i]=12, arr[j]=2
  4. 交换后,i=1, j=8; arr[i]=2, arr[j]=12
  5. ---
  6. 跳过,i=2; arr[i]=5, pivot=7
  7. 交换前,i=3, j=7; arr[i]=26, arr[j]=7
  8. 交换后,i=3, j=7; arr[i]=7, arr[j]=26
  9. ---
  10. 交换前,i=4, j=6; arr[i]=7, arr[j]=3
  11. 交换后,i=4, j=6; arr[i]=3, arr[j]=7
  12. ---
  13. 跳过,j=5; arr[j]=14, pivot=7
  14. 递归 左侧,left=0, index=5
  15. pivot=5; left=0; right=4
  16. 跳过,i=0; arr[i]=1, pivot=5
  17. 跳过,i=1; arr[i]=2, pivot=5
  18. 交换前,i=2, j=4; arr[i]=5, arr[j]=3
  19. 交换后,i=2, j=4; arr[i]=3, arr[j]=5
  20. ---
  21. 跳过,j=3; arr[j]=7, pivot=5
  22. 递归 左侧,left=0, index=3
  23. pivot=2; left=0; right=2
  24. 跳过,i=0; arr[i]=1, pivot=2
  25. 跳过,j=2; arr[j]=3, pivot=2
  26. 交换前,i=1, j=1; arr[i]=2, arr[j]=2
  27. 交换后,i=1, j=1; arr[i]=2, arr[j]=2
  28. ---
  29. 递归 左侧,left=0, index=2
  30. pivot=1; left=0; right=1
  31. 跳过,j=1; arr[j]=2, pivot=1
  32. 交换前,i=0, j=0; arr[i]=1, arr[j]=1
  33. 交换后,i=0, j=0; arr[i]=1, arr[j]=1
  34. ---
  35. 递归右侧,right=4, index=3
  36. pivot=7; left=3; right=4
  37. 交换前,i=3, j=4; arr[i]=7, arr[j]=5
  38. 交换后,i=3, j=4; arr[i]=5, arr[j]=7
  39. ---
  40. 递归右侧,right=8, index=5
  41. pivot=7; left=5; right=8
  42. 跳过,j=8; arr[j]=12, pivot=7
  43. 跳过,j=7; arr[j]=26, pivot=7
  44. 交换前,i=5, j=6; arr[i]=14, arr[j]=7
  45. 交换后,i=5, j=6; arr[i]=7, arr[j]=14
  46. ---
  47. 递归右侧,right=8, index=6
  48. pivot=26; left=6; right=8
  49. 跳过,i=6; arr[i]=14, pivot=26
  50. 交换前,i=7, j=8; arr[i]=26, arr[j]=12
  51. 交换后,i=7, j=8; arr[i]=12, arr[j]=26
  52. ---
  53. 递归 左侧,left=6, index=8
  54. pivot=14; left=6; right=7
  55. 交换前,i=6, j=7; arr[i]=14, arr[j]=12
  56. 交换后,i=6, j=7; arr[i]=12, arr[j]=14
  57. ---
  58. 快速排序
  59. 1 2 3 5 7 7 12 14 26

排序算法系列:快速排序算法JAVA版(靠谱、清晰、真实、可用、不罗嗦版)的更多相关文章

  1. JAVA算法系列 快速排序

    java算法系列之排序 手写快排 首先说一下什么是快排,比冒泡效率要高,快排的基本思路是首先找到一个基准元素,比如数组中最左边的那个位置,作为基准元素key,之后在最左边和最右边设立两个哨兵,i 和 ...

  2. 【排序算法】快速排序算法 Java实现

    快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod). 基本思想 先从数组中找出一个数作为基 ...

  3. java 合并排序算法、冒泡排序算法、选择排序算法、插入排序算法、快速排序算法的描述

    算法是在有限步骤内求解某一问题所使用的一组定义明确的规则.通俗点说,就是计算机解题的过程.在这个过程中,无论是形成解题思路还是编写程序,都是在实施某种算法.前者是推理实现的算法,后者是操作实现的算法. ...

  4. c#冒泡排序算法和快速排序算法

    依次比较相邻的两个数,将小数放在前面,大数放在后面. 第1趟: 首先比较第1个和第2个数,将小数放前,大数放后.然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放 ...

  5. Java实现 蓝桥杯 算法提高 快速排序

    试题 算法提高 快速排序 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 用递归来实现快速排序(quick sort)算法.快速排序算法的基本思路是:假设要对一个数组a进行排序,且a ...

  6. 快速排序算法(C)

    sort快排函数的基本版,效率n*logn,快排的完全版就是在递归之中夹杂对序列的预判断,最优的选择排序方法,快速排序算法只是其中之一. 简单的说明一下快速排序的思想,对于一个数列,首先选择一个基数( ...

  7. 常用算法1 - 快速排序 & 二分查找

    1. 二分查找法: 二分查找法是对一组有序的数字中进行查找,传递相应的数据,进行比较查找到与原数据相同的数据,查找到了返回对应的数组下标,没有找到返回-1. 二分查找法要求数据为一组有序的序列(大到小 ...

  8. c++ 图解快速排序算法

    第一.算法描述 快速排序由C. A. R. Hoare在1962年提出,该算法是目前实践中使用最频繁,实用高效的最好排序算法, 快速排序算法是采用分治思想的算法,算法分三个步骤 从数组中抽出一个元素作 ...

  9. Algorithms - Quicksort - 快速排序算法

    相关概念 快速排序法 Quicksort 也是一个分治思想的算法. 对一个子数组 A[p: r] 进行快速排序的三步分治过程: 1, 分解. 将数组 A[p : r] 被划分为两个子数组(可能为空) ...

随机推荐

  1. 20175314 《Java程序设计》迭代和JDB

    20175314 <Java程序设计>迭代和JDB 要求 1 使用C(n,m)=C(n-1,m-1)+C(n-1,m)公式进行递归编程实现求组合数C(m,n)的功能 2 m,n 要通过命令 ...

  2. 清理xcode

    移除 Xcode 运行安装 APP 产生的缓存文件(DerivedData) ~/Library/Developer/Xcode/DerivedData 移除 APP 打包的ipa历史版本(Archi ...

  3. Powershell 脚本判断制定路径下文件是否存在(来源于网络-转载)

    $filelist=gc "file.txt" #获取要检查的文件列表 $csvs= new-object collections.arraylist #创建一个arraylist ...

  4. CSS的六大选择器

    选择器:选择器是一种模式,用于选择需要添加样式的元素. 首先简述六大选择器 基本选择器 标签选择器 类选择器 ID选择器 高级选择器 层次选择器 结构伪类选择器 属性选择器 其中基本选择器与层次选择器 ...

  5. 21. pt-stalk

    pt-stalk 适用场景:MySQL Server 性能波动出现的频率很低.例如.几天一次MySQL Server 性能波动出现的机率很快.例如.几秒闪过 pt-stalk h=192.168.10 ...

  6. bittorrent 学习(一) 种子文件分析与bitmap位图

    终于抽出时间来进行 BITTORRENT的学习了 BT想必大家都很熟悉了,是一种文件分发协议.每个下载者在下载的同时也在向其他下载者分享文件. 相对于FTP HTTP协议,BT并不是从某一个或者几个指 ...

  7. 1.编译cartographer ROS

    1.系统要求 cartographer ROS与Cartographer要求一样,即 64-bit, modern CPU (e.g. 3rd generation i7) 16 GB RAM Ubu ...

  8. spring与junit整合测试

    1.导包4+2+aop+test 2.配置注解 3.测试

  9. myeclipse 自动部署web项目(自动编译)

    打开自动编译:project->build automatically; 注:以下两种方法适用tomcat配置在myeclipse中的情况. 1.如果在myeclipse中tomcat是以deb ...

  10. wind量化交易

    https://www.joinquant.com/study?f=home&m=memu https://www.v2ex.com/member/mushroomqiu https://sa ...