大家好,又见面了,我是你们的朋友全栈君。
先来复习下找基准的方法:
public static int partion(int[] arr, int start, int end) { int tmp = arr[start];
while (start < end) { while (arr[end] >= tmp && start < end) { --end;
}
if (start >= end) { break;
}else {
arr[start] = arr[end];
}
while (start < end && arr[start] <= tmp) { ++start;
}
if (start >= end) { break;
}else {
arr[end] = arr[start];
}
}
arr[start] = tmp;
return start;
}
后面所有的优化程序都采用该方法来找基准。
一、聚集相同元素法
聚集相同元素排序是快速排序的一种优化方案,它的思路是在经过一次找基准之后把数据中与基准相同的数据聚集到基准左右,这样就可以少进行几次递归找基准的过程,从而提高了运行效率。
看以下程序:
public class FocusAlikeQuickSort {
/** 聚集相同元素 */
public static int[] focusNum(int[] arr, int start, int end, int par) {
int parLeft = par - 1;
int parRight = par + 1;
// 寻找并聚集基准左边与基准相同的元素
for (int i = par - 1; i >= start; i--) {
if (arr[i] == arr[par]) {
if (i != parLeft) {
// 依次遍历比较,相同就交换位置
int tmp = arr[parLeft];
arr[parLeft] = arr[i];
arr[i] = tmp;
parLeft--;
}else {
parLeft--;
}
}
}
// 寻找并聚集基准右边与基准相同的元素
for (int j = par + 1; j <= end; j++) {
if (arr[j] == arr[par]) {
if (j != parRight) {
// 依次遍历比较,相同就交换位置
int tmp = arr[parRight];
arr[parRight] = arr[j];
arr[j] = tmp;
parRight++;
}else {
parRight++;
}
}
}
// 以数组的形式返回聚集相同元素之后的未有序数据的边界
int[] array = new int[2];
array[0] = parLeft;
array[1] = parRight;
return array;
}
public static void quickSort(int[] arr, int start, int end) {
int par = partion(arr, start, end);
// 聚集相同元素
int[] array = focusNum(arr, start, end, par);
int left = array[0];
int right = array[1];
if (par > start + 1) {
quickSort (arr, start, left);
}
if (par < end - 1) {
quickSort (arr, right, end);
}
}
}
运行过程是这样的:
二、随机取基准法
随机取基准法是快速排序的另一种优化方案,它是通过产生随机数的方式在数据中随机选取一个数据来进行找基准操作,次方法较快排在效率上有一定的提高。
看程序:
public class RandomQuickSort {
public static void swap(int [] arr, int start, int end) {
int tmp = arr[start];
arr[start] = arr[end];
arr[end] = tmp;
}
public static void quickSort(int[] arr, int start, int end) {
// 产生在[start, end]之间的随机数
Random rand = new Random();
int randNum = rand.nextInt(end - start + 1) + start;
// 将随机数交换到start位置
swap(arr, start, randNum);
int par = partion(arr, start, end);
if (par > start + 1) {
quickSort (arr, start, par - 1);
}
if (par < end - 1) {
quickSort (arr, par + 1, end);
}
}
}
三、三分取基准法
此方法也是快速排序的一种优化方案,它的思路是比较数据中start,end以及两者中间位置的数据的大小,将这三个值中处于中间位置的值放到首位,再进行找基准操作,此方法较之快排在效率上也有一定的提高。
看程序:
public class ThirdPartitionQuickSort {
/** 交换方法 */
public static void swap(int [] arr, int start, int end) {
int tmp = arr[start];
arr[start] = arr[end];
arr[end] = tmp;
}
/** 比较结束后开始值,中间值和结尾值有序 */
public static void SelectPivotMedianOfThree(int arr[], int low, int high){
int mid = low + ((high - low) >> 1);
// 确定中间值小于结尾值
if (arr[mid] > arr[high]) {
swap(arr, mid, high);
}
// 确定开始值小于结尾值
if (arr[low] > arr[high]) {
swap(arr, low, high);
}
// 确定开始值大于中间值
if (arr[mid] > arr[low]) {
swap(arr, mid, low);
}
}
public static void quickSort(int[] arr, int start, int end) {
// 三分确定首位
SelectPivotMedianOfThree(arr, start, end);
int par = partion(arr, start, end);
if (par > start + 1) {
quickSort (arr, start, par - 1);
}
if (par < end - 1) {
quickSort (arr, par + 1, end);
}
}
}
以上三种方式以及上文末尾提到的优化方法往往结合使用,这样优化后的效率才能有明显的提高。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/128005.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...