package Sort;
import java.text.SimpleDateFormat;
import java.util.Date;
public class QuickSort {
public static void main(String[] args) {
//测试 quickSort
/*int [] arr = new int[100000];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * 100000);
}
//print(arr);
Date date1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd hh-mm-ss");
String strDate1 = simpleDateFormat.format(date1);
System.out.println("排序前的时间是"+strDate1);
quickSort(arr,0, arr.length - 1);
Date date2 = new Date();
//SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-mm-dd hh-mm-ss");
String strDate2 = simpleDateFormat.format(date2);
System.out.println("排序后的时间是"+strDate2);
*/
//System.out.println("---------------");
// print(arr);
//测试 quickSort02
int [] arr = new int[29];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * 50);
}
print(arr);
quickSort02(arr,0, arr.length - 1);
System.out.println("---------------");
print(arr);
}
//快速排序:
//思路1:使用中间值作为基准,当且仅当 l < r ,(同时)从左边扫描,找到左边第一个大于等于基准值的数,周到右边第一个小于等于基准值的数
//先判断是否需要交换,如果l < r,则交换它们,否则l >= r 说明左边的已经全部 < 基准值, 右边的全部 > 基准值,否则重复以上操作.
//交换之后,判断是否需要前移一位或者后移一位,防止进入死循环。如 5 5 5 (交换之后)--->5 5 5 如果不根据条件,前移一位或者后移一位
//则方法进入无限循环。
//退出循环之后,判断是否需要进行左递归(区间[left,r])和右递归(区间[l,right])
public static void quickSort(int [] arr, int left, int right){
int l = left;
int r = right;
int pivot = arr[(left + right) / 2];//使用中间值作为基准
int temp = 0;
//当且仅当 l < r
while (l < r){
//同时)从左边扫描,找到左边第一个大于等于基准值的数,周到右边第一个小于等于基准值的数
//找到左边第一个大于等于基准值的数的下标
while (arr[l] < pivot){
l += 1;
}
//找到右边第一个小于等于基准值的数的下标
while (arr[r] > pivot){
r -= 1;
}
//否则l >= r 说明左边的已经全部 < 基准值, 右边的全部 > 基准值
//判断l 和 r 的此时值
//l >= r 此时左边 已经没有大于基准值的数, 右边没有小于基准值的数,本次分组交换退出
if(l >= r){
break;
}
//如果l < r,则交换它们
//否则,交换 l 和 r 的值
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
交换之后,判断是否需要前移一位或者后移一位,防止进入死循环。
// 如 5 5 5 (交换之后)--->5 5 5 如果不根据条件,前移一位或者后移一位
//这时再判断交换之后arr[l] 的值 与 pivot的值的情况,如果arr[l] == pivot,避免死循环
if(arr[l] == pivot){
r -= 1;
}
//这时再判断交换之后arr[r] 的值 与 pivot的值的情况,如果arr[r] == pivot,避免死循环
if(arr[r] == pivot){
l += 1;
}
}
//当一次分割交换结束之后,避免陷入死循环
if(l == r){
l += 1;
r -= 1;
}
//向左递归,左递归的区间是[left,r]
if(left < r){
quickSort(arr,left,r);
}
// //向右递归,右递归的区间是[l,right]
if(right > l){
quickSort(arr,l,right);
}
}
public static void quickSort02(int [] arr, int low, int high){
if(low < high){
int index = getIndex(arr, low, high);
quickSort02(arr,low,index-1);
quickSort02(arr,index+1,high);
}
}
/*
快速排序思路2:使用数组第一个元素作基准值,用 tmp 保存起来
*/
public static int getIndex(int []arr,int low,int high){
int tmp = arr[low];
//首先从后往前遍历
while (low < high){
//首先 从后 往前 遍历,遇到第一个 大于 基准值的时候停下
while (low < high && arr[high] >= tmp){
high--;
}
//把第一个大于基准值的 赋值给low,第一次即赋值给基准值,因为基准值已经另外保存
arr[low] = arr[high];
//然后开始 从前往后 开始扫描,找到第一个大于基准值是停下
while (low < high && arr[low] <= tmp){
low++;
}
//停下之后,找到一个大于基准值的数,把它交换给arr[high], 因为前面arr[high]的原值已经被交换到arr[low]
arr[high] = arr[low];
//这时,如果 low < high , 则继续从后往前 重复上面两个 内层while循环
}
//退出循环后,low == high,即基准值要插入的地方
arr[low] = tmp;
//返回下一次开始 分割 的下标low--->index,分成[low,index-1],[index+1,high],
//注意:返回值后,此时的low high 是未变化的,因为值传递
return low;
}
public static void print(int [] array){
for (int i = 0; i < array.length; i++) {
System.out.printf("%d ",array[i]);
/*if(i % 50 == 0){
System.out.println();
}*/
}
System.out.println();
// System.out.println(count);
}
}
数据结构排序算法之快速排序的两种实现方法加完整注释及测试
最新推荐文章于 2024-07-24 20:25:39 发布