簡單排序算法時間空間複雜度分析及應用(8)-歸併排序

歸併排序採用的是分治的思想,先把數據集和分成兩個子數據集合進行歸併排序,然後將已經排好序的兩個子序列合併成一個有序的數據集合,歸併排序是一個非常穩定的排序算法。

基本概念:

  歸併排序具體算法描述如下(遞歸版本):

    1、Divide: 把長度爲n的輸入序列分成兩個長度爲n/2的子序列。

    2、Conquer: 對這兩個子序列分別採用歸併排序。

    3、Combine: 將兩個排序好的子序列合併成一個最終的排序序列。

框架分析:

 1.歸併排序算法核心是已排序的兩個子序列合併的步驟

 2.分爲兩個子序列的操作有log(n)次就到最小序列了

 3.合併操作和合並完成後的序列長度n有關

在合併步驟中,會創建一個大小和兩個子序列打大小和一樣的數組空間,排序過程中會有3個循環

體,不過這些循環體都是並列的,沒有嵌套循環,在最外面也有個循環,這個循環大小爲新建數組空間大小

。三個內循環,第一個循環就是比較兩個子序列 元素的大小,選出符合條件的數知道其中一個子序列數據

比較完了,再執行接下來的循環體:將另一個還有數據的子序列的數插入新建的臨時空間中去,這樣就得到了一個排序完全的數據集合。

算法穩定性:歸併排序是一個非常穩定的排序算法。

代碼實現:

	/*
	 * mergesort 歸併排序
	 * @param true 爲增序排列,相反爲降序排列
	 * 時間複雜度爲O(nlog(n))
	 */
	public static void mergeSort(boolean flag){
		
		apart(array , 0 , array.length-1 , flag);
	}		
	private static void apart(int[] array2, int i, int j , boolean flag) {
		// TODO Auto-generated method stub
		if(i >= j) return ;
		int p;
		p = (i+j)/2;
		apart(array2 , i , p , flag);
		apart(array2 , p+1 , j , flag);
		merge(array2 , i , p , j , flag);
	}

	private static void merge(int[] array2, int i, int p, int j , boolean flag) {
		// TODO Auto-generated method stub
		
		int [] arr = new int [j-i+1];
		int m , n ,index;
		m = i ;
		n = p+1;
		index = 0;
		while(m <= p&&n <= j){
			if((array2[m]>=array2[n]&&flag)||(array2[m]<array2[n]&&!flag))
			{
				arr[index] = array2[n];
				++index;
				++n;
			}
			else 
			{
				arr[index] = array2[m];
				++index;
				++m;
			}
		}
		while(m <= p)
		{
			arr[index] = array2[m];
			++index;
			++m;
		}
		while(n <= j)
		{
			arr[index] = array2[n];
			++index;
			++n;
		}
		for(int x = i ; x <= j ; ++ x)
			array2[x] = arr[x-i];
	}

算法複雜度:每個 分治都會有一個合併,經過log(n)次後,分成最小數組,每次都會有n次合併操作,即

nlog(n)

算法比較:  歸併排序的效率是比較高的,設數列長爲N將數列分開成小數列一共要logN步,每步都是一個合併有序數列的過程,時間複雜度可以記爲O(N),故一共爲O(N*logN)。因爲歸併排序每次都是在相鄰的數據中進行操作,所以歸併排序在O(N*logN)的幾種排序方法(快速排序,歸併排序,希爾排序,堆排序)也是效率比較高的


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