排序算法系列:快速排序算法JAVA版(靠谱、清晰、真实、可用、不罗嗦版)
在网上搜索算法的博客,发现一个比较悲剧的现象非常普遍:
- 原理讲不清,混乱
- 啰嗦
- 图和文对不上
- 不可用,甚至代码还出错
为了不误人子弟耽误时间,推荐看一些靠谱的资源,如【啊哈!算法】系列:
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实现(真实可用):
- package Sort;
- public class QuickSort {
- public static void main(String[] args) {
- int arr[] = {1, 12, 5, 26, 7, 14, 3, 7, 2};
- int n = arr.length;
- QuickSort ob = new QuickSort();
- ob.quickSort(arr, 0, n-1);
- //ob.sort(arr, 0, n-1);
- System.out.println("快速排序结果:");
- printArray(arr);
- }
- int partition(int arr[], int left, int right){
- int i = left, j = right;
- int tmp;
- int pivot = arr[(left + right) / 2];
- System.out.println("pivot="+pivot+"; left="+left+"; right="+right);
- while (i <= j) {
- while (arr[i] < pivot){
- System.out.println("跳过,i="+i+"; arr[i]="+arr[i]+", pivot="+pivot);
- i++;
- }
- while (arr[j] > pivot){
- System.out.println("跳过,j="+j+"; arr[j]="+arr[j]+", pivot="+pivot);
- j--;
- }
- if (i <= j) {
- System.out.println("交换前,i="+i+", j="+j+"; arr[i]="+arr[i]+", arr[j]="+arr[j]);
- tmp = arr[i];
- arr[i] = arr[j];
- arr[j] = tmp;
- System.out.println("交换后,i="+i+", j="+j+"; arr[i]="+arr[i]+", arr[j]="+arr[j]);
- System.out.println("---");
- i++;
- j--;
- }
- };
- return i;
- }
- void quickSort(int arr[], int left, int right) {
- int index = partition(arr, left, right);
- if (left < index - 1){
- System.out.println("递归 左侧,left="+left+", index="+index);
- quickSort(arr, left, index - 1);
- }
- if (index < right){
- System.out.println("递归右侧,right="+right+", index="+index);
- quickSort(arr, index, right);
- }
- }
- static void printArray(int arr[])
- {
- int n = arr.length;
- for (int i=0; i<n; ++i)
- System.out.print(arr[i]+" ");
- System.out.println();
- }
- //另一种简洁写法
- int partition1(int arr[], int low, int high)
- {
- int pivot = arr[high];
- int i = (low-1);
- for (int j=low; j<high; j++)
- {
- if (arr[j] <= pivot)
- {
- i++;
- int temp = arr[i];
- arr[i] = arr[j];
- arr[j] = temp;
- }
- }
- int temp = arr[i+1];
- arr[i+1] = arr[high];
- arr[high] = temp;
- return i+1;
- }
- void sort(int arr[], int low, int high)
- {
- if (low < high)
- {
- int pi = partition1(arr, low, high);
- sort(arr, low, pi-1);
- sort(arr, pi+1, high);
- }
- }
- }
调试信息:
- pivot=7; left=0; right=8
- 跳过,i=0; arr[i]=1, pivot=7
- 交换前,i=1, j=8; arr[i]=12, arr[j]=2
- 交换后,i=1, j=8; arr[i]=2, arr[j]=12
- ---
- 跳过,i=2; arr[i]=5, pivot=7
- 交换前,i=3, j=7; arr[i]=26, arr[j]=7
- 交换后,i=3, j=7; arr[i]=7, arr[j]=26
- ---
- 交换前,i=4, j=6; arr[i]=7, arr[j]=3
- 交换后,i=4, j=6; arr[i]=3, arr[j]=7
- ---
- 跳过,j=5; arr[j]=14, pivot=7
- 递归 左侧,left=0, index=5
- pivot=5; left=0; right=4
- 跳过,i=0; arr[i]=1, pivot=5
- 跳过,i=1; arr[i]=2, pivot=5
- 交换前,i=2, j=4; arr[i]=5, arr[j]=3
- 交换后,i=2, j=4; arr[i]=3, arr[j]=5
- ---
- 跳过,j=3; arr[j]=7, pivot=5
- 递归 左侧,left=0, index=3
- pivot=2; left=0; right=2
- 跳过,i=0; arr[i]=1, pivot=2
- 跳过,j=2; arr[j]=3, pivot=2
- 交换前,i=1, j=1; arr[i]=2, arr[j]=2
- 交换后,i=1, j=1; arr[i]=2, arr[j]=2
- ---
- 递归 左侧,left=0, index=2
- pivot=1; left=0; right=1
- 跳过,j=1; arr[j]=2, pivot=1
- 交换前,i=0, j=0; arr[i]=1, arr[j]=1
- 交换后,i=0, j=0; arr[i]=1, arr[j]=1
- ---
- 递归右侧,right=4, index=3
- pivot=7; left=3; right=4
- 交换前,i=3, j=4; arr[i]=7, arr[j]=5
- 交换后,i=3, j=4; arr[i]=5, arr[j]=7
- ---
- 递归右侧,right=8, index=5
- pivot=7; left=5; right=8
- 跳过,j=8; arr[j]=12, pivot=7
- 跳过,j=7; arr[j]=26, pivot=7
- 交换前,i=5, j=6; arr[i]=14, arr[j]=7
- 交换后,i=5, j=6; arr[i]=7, arr[j]=14
- ---
- 递归右侧,right=8, index=6
- pivot=26; left=6; right=8
- 跳过,i=6; arr[i]=14, pivot=26
- 交换前,i=7, j=8; arr[i]=26, arr[j]=12
- 交换后,i=7, j=8; arr[i]=12, arr[j]=26
- ---
- 递归 左侧,left=6, index=8
- pivot=14; left=6; right=7
- 交换前,i=6, j=7; arr[i]=14, arr[j]=12
- 交换后,i=6, j=7; arr[i]=12, arr[j]=14
- ---
- 快速排序
- 1 2 3 5 7 7 12 14 26
排序算法系列:快速排序算法JAVA版(靠谱、清晰、真实、可用、不罗嗦版)的更多相关文章
- JAVA算法系列 快速排序
java算法系列之排序 手写快排 首先说一下什么是快排,比冒泡效率要高,快排的基本思路是首先找到一个基准元素,比如数组中最左边的那个位置,作为基准元素key,之后在最左边和最右边设立两个哨兵,i 和 ...
- 【排序算法】快速排序算法 Java实现
快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod). 基本思想 先从数组中找出一个数作为基 ...
- java 合并排序算法、冒泡排序算法、选择排序算法、插入排序算法、快速排序算法的描述
算法是在有限步骤内求解某一问题所使用的一组定义明确的规则.通俗点说,就是计算机解题的过程.在这个过程中,无论是形成解题思路还是编写程序,都是在实施某种算法.前者是推理实现的算法,后者是操作实现的算法. ...
- c#冒泡排序算法和快速排序算法
依次比较相邻的两个数,将小数放在前面,大数放在后面. 第1趟: 首先比较第1个和第2个数,将小数放前,大数放后.然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放 ...
- Java实现 蓝桥杯 算法提高 快速排序
试题 算法提高 快速排序 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 用递归来实现快速排序(quick sort)算法.快速排序算法的基本思路是:假设要对一个数组a进行排序,且a ...
- 快速排序算法(C)
sort快排函数的基本版,效率n*logn,快排的完全版就是在递归之中夹杂对序列的预判断,最优的选择排序方法,快速排序算法只是其中之一. 简单的说明一下快速排序的思想,对于一个数列,首先选择一个基数( ...
- 常用算法1 - 快速排序 & 二分查找
1. 二分查找法: 二分查找法是对一组有序的数字中进行查找,传递相应的数据,进行比较查找到与原数据相同的数据,查找到了返回对应的数组下标,没有找到返回-1. 二分查找法要求数据为一组有序的序列(大到小 ...
- c++ 图解快速排序算法
第一.算法描述 快速排序由C. A. R. Hoare在1962年提出,该算法是目前实践中使用最频繁,实用高效的最好排序算法, 快速排序算法是采用分治思想的算法,算法分三个步骤 从数组中抽出一个元素作 ...
- Algorithms - Quicksort - 快速排序算法
相关概念 快速排序法 Quicksort 也是一个分治思想的算法. 对一个子数组 A[p: r] 进行快速排序的三步分治过程: 1, 分解. 将数组 A[p : r] 被划分为两个子数组(可能为空) ...
随机推荐
- 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 要通过命令 ...
- 清理xcode
移除 Xcode 运行安装 APP 产生的缓存文件(DerivedData) ~/Library/Developer/Xcode/DerivedData 移除 APP 打包的ipa历史版本(Archi ...
- Powershell 脚本判断制定路径下文件是否存在(来源于网络-转载)
$filelist=gc "file.txt" #获取要检查的文件列表 $csvs= new-object collections.arraylist #创建一个arraylist ...
- CSS的六大选择器
选择器:选择器是一种模式,用于选择需要添加样式的元素. 首先简述六大选择器 基本选择器 标签选择器 类选择器 ID选择器 高级选择器 层次选择器 结构伪类选择器 属性选择器 其中基本选择器与层次选择器 ...
- 21. pt-stalk
pt-stalk 适用场景:MySQL Server 性能波动出现的频率很低.例如.几天一次MySQL Server 性能波动出现的机率很快.例如.几秒闪过 pt-stalk h=192.168.10 ...
- bittorrent 学习(一) 种子文件分析与bitmap位图
终于抽出时间来进行 BITTORRENT的学习了 BT想必大家都很熟悉了,是一种文件分发协议.每个下载者在下载的同时也在向其他下载者分享文件. 相对于FTP HTTP协议,BT并不是从某一个或者几个指 ...
- 1.编译cartographer ROS
1.系统要求 cartographer ROS与Cartographer要求一样,即 64-bit, modern CPU (e.g. 3rd generation i7) 16 GB RAM Ubu ...
- spring与junit整合测试
1.导包4+2+aop+test 2.配置注解 3.测试
- myeclipse 自动部署web项目(自动编译)
打开自动编译:project->build automatically; 注:以下两种方法适用tomcat配置在myeclipse中的情况. 1.如果在myeclipse中tomcat是以deb ...
- wind量化交易
https://www.joinquant.com/study?f=home&m=memu https://www.v2ex.com/member/mushroomqiu https://sa ...