1. 程式人生 > >排序演算法:氣泡排序、插入排序、選擇排序、快速排序對比

排序演算法:氣泡排序、插入排序、選擇排序、快速排序對比

package com.test;

public class T {
	public static void main(String[] args) {

		long start = System.currentTimeMillis();
		int[] arr1 = createArray();
		int[] arr2 = createArray();
		int[] arr3 = createArray();
		int[] arr4 = createArray();

		quick_sort qs = new quick_sort();
		long end = System.currentTimeMillis();
		System.out.println("Creating arrays uses time: " + (end - start));

		start = System.currentTimeMillis();
		bubble_sort(arr1);
		end = System.currentTimeMillis();
		System.out.println("氣泡排序: " + (end - start));

		start = System.currentTimeMillis();
		insertion_sort(arr3);
		end = System.currentTimeMillis();
		System.out.println("插入排序: " + (end - start));

		start = System.currentTimeMillis();
		selection_sort(arr2);
		end = System.currentTimeMillis();
		System.out.println("選擇排序: " + (end - start));

		start = System.currentTimeMillis();
		qs.sort(arr4);
		end = System.currentTimeMillis();
		System.out.println("快速排序: " + (end - start));

		/*
		 * Creating arrays uses time: 16 氣泡排序: 4651 插入排序: 1465 選擇排序: 1399 快速排序:
		 * 14
		 */

	}

	public static int[] createArray() {
		int length = 60000;
		int[] arr = new int[length];

		int i = 0;
		for (; i < length; i++) {
			arr[i] = (int) (Math.random() * length);
		}
		return arr;
	}

	/**
	 * 氣泡排序:
	 * 
	 * 一、 重複的遍歷要排序的序列 n 次。(n為陣列的長度) 二、 對於每次遍歷: 2.1 要遍歷的元素個數減 1 (因為尾部的已經排好) 2.2
	 * 每次都要比較兩個元素。如果符合條件,則交換位置。
	 */
	public static void bubble_sort(int[] arr) {
		int i, j, temp, len = arr.length;
		// 1. 遍歷 i 次
		for (i = 0; i < len - 1; i++)
			// 2. 對於 0 到 len-i 中的元素
			for (j = 0; j < len - 1 - i; j++)
				// 3. 如果前面的大,則交換(冒泡)到後面
				if (arr[j] > arr[j + 1]) {
					temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
				}
	}

	/**
	 * 插入排序:
	 * 
	 * 一、從陣列的第1個元素開始遍歷至第n個。(n為陣列的長度) 二、對於每一個遍歷到的元素: 2.1 向前倒著找(已經排好序的)自己的位置。 2.2
	 * 如果不符合條件,則前面的元素向後移動,與之互動位置。 直至條件符合。
	 */
	public static void insertion_sort(int[] arr) {
		for (int i = 0; i < arr.length - 1; i++) { // 1. 遍歷每一個 i
			for (int j = i + 1; j > 0; j--) { // 2. 從 0-j 是已經排序好的。
				if (arr[j - 1] <= arr[j])
					break; // 位置已經找到,不用再比了。繼續下一個 i
				// 對於每一個 i,向後移動每一個j,騰出空間。直至找到 i 的位置。
				int temp = arr[j];
				arr[j] = arr[j - 1];
				arr[j - 1] = temp;
			}
		}
	}

	/**
	 * 選擇排序:
	 * 
	 * 一、遍歷從 0 到 n 個位置。(n為陣列的長度) 二、對於每一個位置: 2.1 從剩餘的數中找到符合條件的,放到該位置上。
	 */
	public static void selection_sort(int[] arr) {
		int i, j, min, temp, len = arr.length;
		// 1. 遍歷每一個 位置 i
		for (i = 0; i < len - 1; i++) {
			min = i;
			for (j = i + 1; j < len; j++)
				// 2. 遍歷每一個 j,找出最小的
				if (arr[min] > arr[j])
					min = j;
			// 3. 把 找出的值放在 i 的位置
			temp = arr[min];
			arr[min] = arr[i];
			arr[i] = temp;
		}
	}

}

/**
 * 快速排序(Quicksort): 又稱為劃分交換排序(partition-exchange sort)
 * 
 * 快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分為兩個子序列(sub-lists)。 步驟: 1.
 * 從序列中選一個數作為基準(pivot)。【本例中使用最後一個元素】 2. 分別從左右兩側開始向中間推進。 左側:從左至右前進,直至找到大於等於基準的數。
 * 右側:從右至左前進,直至找到小於基準的數。 左右兩個數調換位置。 3. 重複2的過程,直至左右相碰,全部遍歷完一遍。 此時在相碰處:
 * 左側:所有的數都小於基準小。 右側:所有的數都大於或等於基準。 中間:基準元素的位置已確定了。 4. 把相碰處分為兩個子序列,遞迴的呼叫2,3步驟。
 */
class quick_sort {
	int[] arr;

	private void swap(int x, int y) {
		int temp = arr[x];
		arr[x] = arr[y];
		arr[y] = temp;
	}

	private void quick_sort_recursive(int start, int end) {
		if (start >= end)
			return;
		int mid = arr[end];
		int left = start, right = end - 1;

		// 1. left 區先和 right 區比
		while (left < right) {
			while (arr[left] < mid && left < right) // 找到left中比mid大的或相等的。
				left++;
			while (arr[right] >= mid && left < right) // 只找到right中比mid小的。
				right--;
			if (left < right)
				swap(left, right);// 將2個的位置調換。
		}

		// 2. left 區再和 mid 比
		// 如果左側最右邊(右側最左邊)的值比mid大,
		// 則mid要歸小值區。 left的值不加。
		// 即保證:left 區的值都是小的。
		if (arr[left] >= arr[end])
			swap(left, end);
		else
			left++;

		// left 此時為中間值,位置已被最終確定。無需包含 left。
		// 故從 left-1, left + 1 開始。
		quick_sort_recursive(start, left - 1);
		quick_sort_recursive(left + 1, end);
	}

	public void sort(int[] arrin) {
		arr = arrin;
		quick_sort_recursive(0, arr.length - 1);
	}
}

執行結果:

Creating arrays uses time: 10
氣泡排序: 6024
插入排序: 1234
選擇排序: 1092
快速排序: 20