import java.util.Scanner;
import org.junit.Test;
public class Main5 {
/**
* 快排兩頭逼近一趟劃分過程
* @param a 子序列
* @param low 子序列左邊界下標
* @param high 子序列右邊界下標
* @return 基準元素下標
*/
public static int partition(int[] a, int low, int high) {
int key = a[low];// 將子序列第一個元素抽出來作爲基準元素
int tmpLow=low;
int tmpHigh=high;
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 待排序序列
* @param left
* @param right
*/
public static void quickSort(int[] a, int left, int right) {
if (right - left == 0) {// 當待排序列中只有一個元素時,顯然已經有序,結束遞歸
return;
}
int middleIndex = partition(a, left, right);
if(middleIndex!=left){//這個判斷條件必須要加,因爲如果本來就是已經排好序的,那麼第一趟兩頭向中間逼近結束後返回的基準元素下標是0,這個時候再計算middleIndex - 1就會出現負的下標
quickSort(a, left, middleIndex - 1);
}
quickSort(a, middleIndex + 1, right);
}
@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);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
// 1 3 5 3 1 5 2 8 6 8
}
寫在後面的話:快速排序也叫分區排序,是目前應用最廣泛的排序算法,快速排序是一個效率很高的排序算法,但是對於長度很小的序列快速排序算法的速度並不比一些簡單的排序算法快(有研究證明過的),可以對快速排序算法進行改進,設定一個長度L,當子序列長度在0-L的範圍內,可以對子序列進行直接插入排序,這樣就可以提高快速排序的效率了,還可以有效解決一個問題:StackOverflowError,遞歸是一種非常好的思想,遞歸寫的算法簡潔高效,但是遞歸層次過深會導致棧溢出,所以一般不建議使用遞歸。改進的快排算法請看下回分解。