前言
我写这个的时候就有个感觉,就是,思想都好想通,但是落实到代码上,就各种出错,debug了老久,思路推翻了很多次,给我的感觉就是**“容错率”**非常低,出一丁点错,这个算法就失败。
读本文之前建议看下这篇讲解原理的图文分析:http://developer.51cto.com/art/201403/430986.htm
本文称:
- 1.当2个元素的index相遇为**“碰撞”**
- 2.用来作比较的基准值在这里称为**“标尺”**
理解:
个人觉得这个排序算法的核心在于——订立一个标尺,比标尺小的值放在左边,比标尺大的数放右边。
分析过程:
- 1.从左往右找比标尺大的值
- 2.从右往左找比标尺小的值
- 3.找到之后,判断当前ij是否相碰撞了,发生了碰撞则表示一趟结束,此时(跳出循环)进行递归,进行下一趟排序
- 4.当元素未发生碰撞时 交换二者元素并重复循环
- 5.当元素发生碰撞时,置换换key元素位置,并跳出循环进行下一趟排序
- 6.递归 分别排序标尺左边和右边
代码
/**
* @param a 数组
* @param left 区间开始
* @param right 区间结束
*/
public static void quickSort(int[] a, int left, int right) {
//begin和end记录初始的区间范围,i,j是用来做角标的频繁跳动。
int temp;
int i = left;
int j = right;
//7.
if (left > right) {
return;
}
while (true) {
//1.
while (j > i && a[j] > a[left]) {
j--;
}
//2.
while (i < j && a[i] < a[left]) {
i++;
}
//3.
if (i == j) {
//5.
temp = a[left];
a[i] = a[left];
a[left] = temp;
break;
} else {
//4.
temp = a[i];
a[i] = a[j];
a[j] = temp;
continue;
}
}
//6.
quickSort(a, left, i - 1);//左边
quickSort(a, i + 1, right);//右边
}
顺口说一下写的时候躺的坑吧:
- 递归的时候一定要给出口。另外递归的时候一定要放在一趟排序流程之外。
- key换位置的时候一定要想清楚,ij碰撞,起始点和ij角标位置置换。
- 没有碰撞的时候记得continue
输出信息
o开始开始:[31, 8, 66, 1, 22, 9, 11]
趟数1中途:[11, 8, 66, 1, 22, 9, 31]
趟数1中途:[9, 8, 66, 1, 22, 11, 31]
趟数1中途:[1, 8, 66, 9, 22, 11, 31]
趟数1碰撞:[1, 8, 66, 9, 22, 11, 31]
趟数2碰撞:[1, 8, 66, 9, 22, 11, 31]
趟数3中途:[1, 8, 31, 9, 22, 11, 66]
趟数3中途:[1, 8, 11, 9, 22, 31, 66]
趟数3中途:[1, 8, 9, 11, 22, 31, 66]
趟数3碰撞:[1, 8, 9, 11, 22, 31, 66]
趟数4碰撞:[1, 8, 9, 11, 22, 31, 66]
趟数5碰撞:[1, 8, 9, 11, 22, 31, 66]
趟数6碰撞:[1, 8, 9, 11, 22, 31, 66]
趟数7碰撞:[1, 8, 9, 11, 22, 31, 66]
o结束结束:[1, 8, 9, 11, 22, 31, 66]
Demo
https://github.com/zj614android/algorithm/blob/master/QuickSort.java
Thanks
分治
https://www.cnblogs.com/yanlingyin/archive/2012/04/16/2441979.html
坐在马桶上看算法:快速排序
http://developer.51cto.com/art/201403/430986.htm
快排视频
http://www.iqiyi.com/v_19rrhzyeqs.html