歸併排序

歸併排序,整體就是一個簡單的遞歸過程,左邊排好序,右邊排好序,讓其整體有序。讓其整體有序的過程中用到了外排序的方法。
坦白的說,這種排序不好去理解,歸併的代碼我是看了好久才學會的,自己也練了好多遍,感覺還是暈暈的,這種排序要靠自己去領悟的,我是用最笨的方法,把所有執行的過程全部寫出來,結果自己看懂了!順便也推出的它的時間複雜度,實在不好用語言說清楚的;下面我就先寫出代碼;然後畫圖推出它的時間複雜度;

	public class Code_MergeSort {
	private static final int[] arr = { 20, 17, 18, 11, 10 };

	public static void main(String[] args) {
		mergeSort(arr, 0, arr.length - 1);
	}

	/**
	 * @param arr
	 *            數組
	 * @param left
	 *            數組的左邊開始下標
	 * @param right
	 *            數組的右邊開始下標
	 */
	private static void mergeSort(int[] arr, int left, int right) {
		if (left == right)
			return;
		int middle = left + ((right - left) >> 1);// 中間的下標
		mergeSort(arr, left, middle);// 左邊遞歸
		mergeSort(arr, middle + 1, right);// 右邊遞歸
		merge(arr, left, middle, right);// 兩邊都調用完了遞歸以後使用外排序的方法
	}

	private static void merge(int[] arr, int left, int middle, int right) {
		int[] help = new int[right - left + 1];// 輔助數組,大小相同起始結束位置相同
		int i = 0;// 輔助數組的起始下標
		int p1 = left;// 左邊數組的起始的下標
		int p2 = middle + 1;// 右邊數組的起始的下標

		while ((p1 <= middle) // 左邊數組不越界
				&& (p2 <= right)) // 右邊數組不越界
		{
			help[i++] = (arr[p1] < arr[p2]) ? arr[p1++] : arr[p2++];
		}
		//執行完上邊以後一個越界,一個不越界,把不越界的數組全部copy到輔助數組之中
		while (p1 <= middle) {
			help[i++] = arr[p1++];
		}
		while (p2 <= right) {
			help[i++] = arr[p2++];
		}
		for (int j = 0; j < help.length; j++) {
			arr[left + j] = help[j];
		}
	}
}

以上就是全部的代碼:
下面列出上面代碼執行的所有過程;
比如下面這個數組:

數組下標index 0 1 2 3 4
數組數值value 20 17 18 11 10

按照上面的代碼簡單的執行過程如下面的圖所示:
在這裏插入圖片描述
畫紅色的方框代表結束遞歸結束,這樣的次數和數組的大小相同;
其他的都是遞歸自身的外排序方法;

現在我們來估算它的時間複雜度:
假設數組的長度是N個;上面的結構是一個二叉樹的結構,他實際上的高度是多少(不包含像紅色方框的數據)
,根據公式總共有:log2N層的高度,那麼每一層的執行的次數的多少呢?也就是外排序方法執行的次數是多少;
第一層 N長度數組------要執行N次;
第二層 N/2長度數組-----要執行(N/2)次;
第三層 N/4長度數組-----要執行(N/4)次;
第四層 N/8長度數組-----要執行(N/8)次;
第五層 N/16長度數組-----要執行(N/16)次;

上面就是最差情況;
所以時間複雜度的推導公式 f(N) = N+(N/2)+…;總共有log2N個,
所以時間複雜度是
(x(1-(1/2)x))/(1-(1/2)),
把x=log2N帶入上面的公式 得出時間複雜度是Nlog2N
所以歸併排序的時間複雜度是O(n) = n
log2n;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章