1. 程式人生 > >資料結構之氣泡排序(java)

資料結構之氣泡排序(java)

氣泡排序可以說是最簡單的排序演算法,但不意味著它不重要。

理解氣泡排序,可以帶出以下問題。

1.氣泡排序只有一個基本操作,就是比較和交換相鄰的兩個元素,可以提現將一個複雜問題轉化為簡單問題的疊加的思想。

2.氣泡排序的兩層for迴圈該如何理解。

3.分析時間複雜度簡單,程式碼很短,一眼就能看出是O(n^2)。

4.分析完氣泡排序可以發現,其他O(n^2)級別的演算法或多或少與氣泡排序有共同之處:用O(n)的複雜度來排好一個元素。理解完氣泡排序,之後便於理解其他O(n^2)級別的演算法。

舉個栗子:   -->4 3 2 7 1 6 5

第一層for迴圈:e=6,即確定第6個位置的值

第二層for迴圈:i=0,比較a[0]與a[1],4>3,交換a[0]與a[1]的位置,陣列變為:3 4

2 7 1 6 5

                          i=1,比較a[1]與a[2],4>2,交換a[1]與a[2]的位置,陣列變為:3 2 4 7 1 6 5

                          i=2,比較a[2]與a[3],4<7,不交換

                          i=3,比較a[3]與a[4],7>1,交換a[3]與a[4]的位置,陣列變為:3 4 2 1 7 6 5

                          i=4,比較a[4]與a[5],7>6,交換a[0]與a[1]的位置,陣列變為:3 4 2 1 6 7

5

                          i=5,比較a[5]與a[6],7>5,交換a[0]與a[1]的位置,陣列變為:3 4 2 7 1 5 7

陣列中的最大數不斷下沉,沉到最後一個位置

之後依次確定倒數第二個位置的數(即次小的數),倒數第三個位置的數,......

氣泡排序實現可以做到穩定性

下面給出氣泡排序的java程式碼:

import java.util.Arrays;

public class BubbleSort {

	public static void bubbleSort(int[] arr) {
		// 若陣列為空,則直接返回。
		if (arr == null || arr.length < 2) {
			return;
		}
		// 將陣列分為未排序區和已排序區。外層for迴圈每迴圈一次,確定已排序區的一個元素。
		for (int e = arr.length - 1; e > 0; e--) {
			for (int i = 0; i < e; i++) {
				if (arr[i] > arr[i + 1]) {
					swap(arr, i, i + 1);
				}
			}
		}
	}

	// 注意:適用情況:i與j不同
	// i代表甲資訊量,j代表乙資訊量
	public static void swap(int[] arr, int i, int j) {
		arr[i] = arr[i] ^ arr[j]; // arr[i] = 甲 ^ 乙
		arr[j] = arr[i] ^ arr[j]; // arr[j] = 甲 ^ 乙 ^ 乙 = 甲 (乙與乙異或為0,甲與0異或為甲)
		arr[i] = arr[i] ^ arr[j]; // arr[i] = 甲 ^ 乙 ^ 甲 ^ 乙 ^ 乙 = 乙;實現交換
	}

	// 比較器
	public static void comparator(int[] arr) {
		Arrays.sort(arr);
	}

	// 生成隨機陣列
	public static int[] generateRandomArray(int maxSize, int maxValue) {
		int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (int) ((maxValue + 1) * Math.random())
					- (int) (maxValue * Math.random());
		}
		return arr;
	}

	// 複製陣列
	public static int[] copyArray(int[] arr) {
		if (arr == null) {
			return null;
		}
		int[] res = new int[arr.length];
		for (int i = 0; i < arr.length; i++) {
			res[i] = arr[i];
		}
		return res;
	}

	// 判斷兩陣列是否相等
	public static boolean isEqual(int[] arr1, int[] arr2) {
		if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
			return false;
		}
		if (arr1 == null && arr2 == null) {
			return true;
		}
		if (arr1.length != arr2.length) {
			return false;
		}
		for (int i = 0; i < arr1.length; i++) {
			if (arr1[i] != arr2[i]) {
				return false;
			}
		}
		return true;
	}

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

	// 用系統提供的的sort函式執行結果與自己寫的氣泡排序執行結果進行比較,若相等,返回nice
	public static void main(String[] args) {
		int testTime = 500000;
		int maxSize = 100;
		int maxValue = 100;
		boolean succeed = true;
		for (int i = 0; i < testTime; i++) {
			int[] arr1 = generateRandomArray(maxSize, maxValue);
			int[] arr2 = copyArray(arr1);
			bubbleSort(arr1);
			comparator(arr2);
			if (!isEqual(arr1, arr2)) {
				succeed = false;
				break;
			}
		}
		System.out.println(succeed ? "Nice!" : "Fucking fucked!");
		// 列印其中一組。
		int[] arr = generateRandomArray(maxSize, maxValue);
		printArray(arr);
		bubbleSort(arr);
		printArray(arr);
	}

}