/*
* 快速排序(默认排成升序)
*
* 解题思路
* (以索引为0的元素为基准)
* 进行一次快排
* 先从后面的索引开始去找比基准数小的数字,找到停
* 再从前面的索引找比基准数大的数字,找到停
* 前后的索引都找到后,交换两个索引所指向的元素的位置
* 再从第一步开始继续往下走
* 当两个索引指针重合的时候,需要把基准数和索引指向的元素进行交换位置,基准数归位
* 当基准数归位后,把序列变成了两个序列,前后两个序列分别做快速排序
*
* 思考问题:
* 一: 为什么要先从右边往左边扫描
* 从左边开始扫描的话 每当开始一次快排.当i与j相撞时,查找到的值都可能比基准值大
* 而结束一次快排前,基准值要和查找到的值交换位置,会导致大的数被交换到左边
*
* 二:为什么要索引扫描时,比较数值大小时要加=号
* 当有两个重复的数值时,会出现反复交换的情况 进入死循环
*
*/
//startIndex为数组开始索引,endIndex为数组结束索引(数组长度减一)
public static void quickSort(int[] arr, int startIndex, int endIndex) {
//若左右索引值相等,结束递归
if (startIndex >= endIndex)
return;
//用i从前往后扫描
int i = startIndex;
//j从后往前扫描
int j = endIndex;
//key存储基准值,默认为索引0的数值
int key = arr[startIndex];
while (i != j) {
//先从后往前找小于等于基准值的数值,找到或i与j相等时就停止
while (i < j && arr[j] >=key)//此处若不加等号 当有两个重复的数值时,会出现反复交换的情况 进入死循环
j--;
//然后从前往后找大于等于基准值的数值,找到或者j与i相等时就停止
while (i < j && arr[i] <=key)//同上
i++;
//当i<j时,交换i,j索引值的数值
if (i<j)//避免自己和自己进行无效的交换
exchange(arr, i, j);
}
//当i=j时,交换基准值与相撞位置的值
exchange(arr, startIndex, j);
//分别对相撞位置值前后的两段数组进行递归排序
quickSort(arr, startIndex, i-1 );//此处为i-1或者为i都不影响结果,但要注意这行与下行代码关于i的索引值不能一样
quickSort(arr, i + 1, endIndex);//
}
//交换数值的方法
public static void exchange(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String[] args) {
int[] a = new int[]{1, 5, 5, 2, 3, 6};
//调用 快排方法
quickSort(a, 0, 5);
for (int i = 0; i < 6; i++) {
System.out.print(a[i]);//输出结果 123556
}
}
}
Java 快速排序
