改进的快速排序算法思想
上一篇博客写了快排的实现代码,也分析了快排使用递归可能出现栈溢出和子序列在长度很短的情况下可以采用其他简单的排序算法来排序以提高快排效率。这种思想就是:当待排序的子序列规模小于预先确定的L时,程序调用折半插入排序或者直接插入排序或其他简单的排序算法进行排序,并结束递归,这样既提高了快排的效率,又可以有效控制栈溢出StackOverflowError。下面附上Java代码。
import java.util.Scanner;
import org.junit.Test;
public class Main6 {
/**
* 快排两头逼近一趟划分过程
* @param a 子序列
* @param low 子序列左边界下标
* @param high 子序列右边界下标
* @return 基准元素下标
*/
public static int partition(int[] a, int low, int high) {
int key = a[low];// 将子序列第一个元素抽出来作为基准元素
while (low < high) {
while (low < high && a[high] >= key) {
high--;
} // 当a[right]<key时退出循环
a[low] = a[high];// 将a[right]移动到前面
while (low < high && a[low] <= key) {
low++;
} // 当a[left]>key时退出循环
a[high] = a[low];// 将a[left]移动到后面
} // 当left==right时,说明一趟两头逼近已经结束,将基准元素插入中间位置
a[low] = key;
return low;
}
/**
* 折半插入排序
* @param a 待排序序列
*/
public static void binaryInsertSort(int[] a,int left,int right) {
for (int i = left + 1; i <= right; i++) {
int temp = a[i];
int low = left;
int middle;
int high = i - 1;// low到high为排好序区间
while (low <= high) {// 利用折半搜索插入位置
middle = (low + high) / 2;// 取中点
if (temp < a[middle]) {// 插入值小于中点值
high = middle - 1;// 向左缩小区间
} else {
low = middle + 1;// 向右缩小区间
}
}
for (int k = i - 1; k >= low; k--) {// 成块移动,空出插入位置
a[k + 1] = a[k];
}
a[low] = temp;// low即为插入位置
}
}
/**
* 改进的快速排序算法
* @param a 待排序子序列
* @param left 子序列左边界下标
* @param right 子序列右边界下标志
* @param L 子序列长度阈值 description:递归结束条件
*/
public static void quickSort(int[] a, int left, int right,int L) {
if (right - left <=L) {// 当待排序列长度小于L时,采用折半插入排序排序子序列,结束递归,避免递归层级调用过深,也能提高效率
binaryInsertSort(a, left, right);
return;
}
int middleIndex = partition(a, left, right);
quickSort(a, left, middleIndex - 1,L);
quickSort(a, middleIndex + 1, right,L);
}
@Test
public void testQuickSort() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入数组长度!");
int n = sc.nextInt();
int[] a = new int[n];
System.out.println("请输入数组元素");
for (int i = 0; i < a.length; i++) {
a[i] = sc.nextInt();
}
int left = 0;
int right = n - 1;
quickSort(a, left, right,4);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
}