1. 程式人生 > >五十道程式設計小題目 --- 28 八大排序演算法 java 之 06快速排序

五十道程式設計小題目 --- 28 八大排序演算法 java 之 06快速排序



6. 交換排序—快速排序(Quick Sort)

快速排序演算法介紹

      快速排序和歸併排序都使用分治法來設計演算法,區別在於歸併排序把陣列分為兩個基本等長的子陣列,分別排好序之後還要進行歸併(Merge)操作,而快速排序拆分子陣列的時候顯得更有藝術,取一個基準元素拆分之後基準元素左邊的元素都比基準元素小,右邊的元素都不小於基準元素,這樣只需要分別對兩個子陣列排序即可,不再像歸併排序一樣需要歸併操作


基本思想:

1)選擇一個基準元素,通常選擇第一個元素或者最後一個元素,

2)通過一趟排序講待排序的記錄分割成獨立的兩部分,其中一部分記錄的元素值均比基準元素值小。另一部分記錄的 元素值比基準值大。

3)此時基準元素在其排好序後的正確位置

4)然後分別對這兩部分記錄用同樣的方法繼續進行排序,直到整個序列有序。

快速排序的示例:

(a)一趟排序的過程:

(b)排序的全過程


演算法的實現:

import java.util.Random;

public class QuickSort {

	// 快速排序
	private static void quickSort(int[] a) {
		System.out.println("在陣列中從0到"+(a.length-1)+"基準元素索引:" + 0);
		subQuickSort(a, 0, a.length-1);
	}
	
	private static void subQuickSort(int[] a,int start, int end) {
		if(a == null || end-start<2){
			return ;
		}
		
		int keyIndex = quickSortPortion(a, start, end);
		System.out.println("在陣列中從"+start+"到"+end+"基準元素索引變換:" + keyIndex);
		if(keyIndex == start){
			subQuickSort(a, start+1, end);
		}else if(keyIndex == end){
			subQuickSort(a, start, end-1);
		}else{
			subQuickSort(a, start, keyIndex-1);
			subQuickSort(a, keyIndex+1, end);
		}
		
		
	}

	private static int quickSortPortion(int[] a, int start, int end) {
		int minIndex = (end-start) / 2 + start; // minIndex定義為陣列的中間索引
		int key = start; // 將陣列的第一個元素的索引定義為基準元素
		int h = end;
		
		
		
		System.out.println("快速排序------------>");
		for (int i = start; i < end; i++) { // 比較 length-1次
			if (key <= minIndex) { // 如果基準元素在前半部分
				if (a[key] > a[h]) { // 元素值比基準元素值小
					swap(a, key, h); // 交換位置
					int tmp = h;
					h = key + 1;
					key = tmp;
				} else {
					h--;
				}
			} else { // 如果基準元素在後半部分
				if (a[key] < a[h]) { // 元素值比基準元素值大
					swap(a, key, h); // 交換位置
					int tmp = key;
					key = h;
					h = tmp - 1;

				} else {
					h++;
				}
			}
			print(a);
		}
//		print(a);
		return key;
	}

	// 交換陣列元素
	private static void swap(int[] arr, int i, int j) {
		if (i == j) {
			return;
		}
		arr[i] = arr[i] + arr[j];
		arr[j] = arr[i] - arr[j];
		arr[i] = arr[i] - arr[j];
	}

	// 列印陣列
	public static void print(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
	}

	public static void main(String[] args) {

		int a[] = { 49, 38, 65, 97, 76, 13, 27, 49 };
		System.out.println("排序前  : ");
		print(a);

		System.out.println("排序  : ");
		quickSort(a);
		print(a);
		
		// System.out.println("任意陣列測試:");
		// Random r = new Random();
		// int[] testArr = new int[20];
		// for (int i = 0; i < 20; i++) {
		// testArr[i] = r.nextInt(100);
		// }
		//
		// System.out.println("排序前 : ");
		// print(testArr);
		//
		// System.out.println("排序後: ");
		// print(quickSort(testArr));

	}

	

}

輸出結果:
排序前  : 
49 38 65 97 76 13 27 49 
排序後 : 
在陣列中從0到7基準元素索引:0
快速排序------------>
49 38 65 97 76 13 27 49 
27 38 65 97 76 13 49 49 
27 38 65 97 76 13 49 49 
27 38 49 97 76 13 65 49 
27 38 13 97 76 49 65 49 
27 38 13 49 76 97 65 49 
27 38 13 49 76 97 65 49 
在陣列中從0到7基準元素索引變換:3
快速排序------------>
13 38 27 49 76 97 65 49 
13 27 38 49 76 97 65 49 
在陣列中從0到2基準元素索引變換:1
快速排序------------>
13 27 38 49 49 97 65 76 
13 27 38 49 49 76 65 97 
13 27 38 49 49 65 76 97 
在陣列中從4到7基準元素索引變換:6
13 27 38 49 49 65 76 97 



分析:

快速排序是一個不穩定的排序方法。

6. 交換排序—快速排序(Quick Sort)

快速排序演算法介紹

      快速排序和歸併排序都使用分治法來設計演算法,區別在於歸併排序把陣列分為兩個基本等長的子陣列,分別排好序之後還要進行歸併(Merge)操作,而快速排序拆分子陣列的時候顯得更有藝術,取一個基準元素拆分之後基準元素左邊的元素都比基準元素小,右邊的元素都不小於基準元素,這樣只需要分別對兩個子陣列排序即可,不再像歸併排序一樣需要歸併操作


基本思想:

1)選擇一個基準元素,通常選擇第一個元素或者最後一個元素,

2)通過一趟排序講待排序的記錄分割成獨立的兩部分,其中一部分記錄的元素值均比基準元素值小。另一部分記錄的 元素值比基準值大。

3)此時基準元素在其排好序後的正確位置

4)然後分別對這兩部分記錄用同樣的方法繼續進行排序,直到整個序列有序。

快速排序的示例:

(a)一趟排序的過程:

(b)排序的全過程


演算法的實現:

import java.util.Random;

public class QuickSort {

	// 快速排序
	private static void quickSort(int[] a) {
		System.out.println("在陣列中從0到"+(a.length-1)+"基準元素索引:" + 0);
		subQuickSort(a, 0, a.length-1);
	}
	
	private static void subQuickSort(int[] a,int start, int end) {
		if(a == null || end-start<2){
			return ;
		}
		
		int keyIndex = quickSortPortion(a, start, end);
		System.out.println("在陣列中從"+start+"到"+end+"基準元素索引變換:" + keyIndex);
		if(keyIndex == start){
			subQuickSort(a, start+1, end);
		}else if(keyIndex == end){
			subQuickSort(a, start, end-1);
		}else{
			subQuickSort(a, start, keyIndex-1);
			subQuickSort(a, keyIndex+1, end);
		}
		
		
	}

	private static int quickSortPortion(int[] a, int start, int end) {
		int minIndex = (end-start) / 2 + start; // minIndex定義為陣列的中間索引
		int key = start; // 將陣列的第一個元素的索引定義為基準元素
		int h = end;
		
		
		
		System.out.println("快速排序------------>");
		for (int i = start; i < end; i++) { // 比較 length-1次
			if (key <= minIndex) { // 如果基準元素在前半部分
				if (a[key] > a[h]) { // 元素值比基準元素值小
					swap(a, key, h); // 交換位置
					int tmp = h;
					h = key + 1;
					key = tmp;
				} else {
					h--;
				}
			} else { // 如果基準元素在後半部分
				if (a[key] < a[h]) { // 元素值比基準元素值大
					swap(a, key, h); // 交換位置
					int tmp = key;
					key = h;
					h = tmp - 1;

				} else {
					h++;
				}
			}
			print(a);
		}
//		print(a);
		return key;
	}

	// 交換陣列元素
	private static void swap(int[] arr, int i, int j) {
		if (i == j) {
			return;
		}
		arr[i] = arr[i] + arr[j];
		arr[j] = arr[i] - arr[j];
		arr[i] = arr[i] - arr[j];
	}

	// 列印陣列
	public static void print(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
	}

	public static void main(String[] args) {

		int a[] = { 49, 38, 65, 97, 76, 13, 27, 49 };
		System.out.println("排序前  : ");
		print(a);

		System.out.println("排序  : ");
		quickSort(a);
		print(a);
		
		// System.out.println("任意陣列測試:");
		// Random r = new Random();
		// int[] testArr = new int[20];
		// for (int i = 0; i < 20; i++) {
		// testArr[i] = r.nextInt(100);
		// }
		//
		// System.out.println("排序前 : ");
		// print(testArr);
		//
		// System.out.println("排序後: ");
		// print(quickSort(testArr));

	}

	

}

輸出結果:
排序前  : 
49 38 65 97 76 13 27 49 
排序後 : 
在陣列中從0到7基準元素索引:0
快速排序------------>
49 38 65 97 76 13 27 49 
27 38 65 97 76 13 49 49 
27 38 65 97 76 13 49 49 
27 38 49 97 76 13 65 49 
27 38 13 97 76 49 65 49 
27 38 13 49 76 97 65 49 
27 38 13 49 76 97 65 49 
在陣列中從0到7基準元素索引變換:3
快速排序------------>
13 38 27 49 76 97 65 49 
13 27 38 49 76 97 65 49 
在陣列中從0到2基準元素索引變換:1
快速排序------------>
13 27 38 49 49 97 65 76 
13 27 38 49 49 76 65 97 
13 27 38 49 49 65 76 97 
在陣列中從4到7基準元素索引變換:6
13 27 38 49 49 65 76 97 



分析:

快速排序是一個不穩定的排序方法。