快速排序详解
说明
- 快速排序是对冒泡排序的一种升级,因此排序速度非常快,典型的以空间换时间的思路
- 先从数组中找一个中间值,这个值的找法有设计者自己定义,可以是数组最中间的值,也可以是数组的最前边或者最后边的值,一般选择中间值
- 找到这个标志值后,将左侧大于这个标志值的数移动到这个值右侧,将右侧小于标志值的数移动到这个值左侧,可以使用交换的思路
- 然后将第一次交换后的数组分成两部分再执行同样的操作,即这个标志值左侧和右侧两部分
- 将这两部分再使用同样的方式,即形成递归,直到所有的元素全部有序为止
- 经测试快速排序效率比希尔排序还快,但递归需要开辟新栈,比较耗时间
- 源码及分析见下
源码及分析
/**
* 快速排序,对冒泡排序的升级
*
* @param arr 要排序的数组
* @param left 左下标
* @param right 右下标
*/
public static void quickSort(int[] arr, int left, int right) {
//定义变量 l 和 r 保存数组的左右元素索引
int l = left, r = right;
//定义变量pivot保存数组的中间值,
//将小于pivot的数放到pivot左边,将大于pivot的数放到pivot右边
int pivot = arr[(l + r) / 2];
//定义辅助变量tmp用于交换数字
int tmp = 0;
//循环执行交换数字的操作
while (l < r) {
//寻找左侧大于pivot的数,循环结束是当前arr[l] >= pivot
while (arr[l] < pivot) {
l++;
}
//寻找右侧小于pivot的数,循环结束时当前arr[r] <= pivot
while (arr[r] > pivot) {
r--;
}
//判断 l 和 r 的大小,如果循环结束时 l == r,说明pivot左侧数全部小于pivot
//pivot右侧的数全部大于pivot
if (l == r) {
break;
}
//否则就交换当测大于pivot的数和右侧小于pivot的数
tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
//如果交换完以后发现arr[l] == pivot ,则r--
if (arr[r] == pivot) {
r--;
}
//如果交换完以后发现arr[r] == pivot ,则l++
if (arr[l] == pivot) {
l++;
}
//如果 l == r,必须进行 l++, r--,否则出现栈溢出
if (r == l) {
r--;
l++;
}
//向左递归
if (left < r) {
quickSort(arr, left, r);
}
//向右递归
if (right > l) {
quickSort(arr, l, right);
}
}
}