改進的快速排序算法思想
上一篇博客寫了快排的實現代碼,也分析了快排使用遞歸可能出現棧溢出和子序列在長度很短的情況下可以採用其他簡單的排序算法來排序以提高快排效率。這種思想就是:當待排序的子序列規模小於預先確定的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] + " ");
}
}
}