如何使用遞歸實現歸併排序

       歸併排序:歸併排序是建立在歸併操作上的一種有效的排序算法,該算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序,稱爲二路歸併

       數據結構的學習過程中,我們經常會遇到排序算法,其中歸併排序是一種高效並且算法複雜度比較簡單的一種。在課本的介紹中,大部分都會介紹歸併排序算法。但是,每次看書總是覺得很容易,自己嘗試去實現時,總是會出錯。學習數據結構已經有一段時間了,但是直接讓我裸寫歸併排序的代碼,也需要花上不少時間去調試。難道就沒有更好的方式讓我們記住代碼嗎? 

       其實只要我們在寫代碼時,注意下技巧,便可輕鬆實現歸併排序算法。下面介紹下我使用的方式:

       第一步:先寫一個合併兩個排序好數組的方法,方法名就叫做merge,如下:

    public static void merge(int[] a, int aSize, int[] b, int bSize, int[] c){
		int tempA = 0, tempB = 0, tempC = 0;
		while(tempA < aSize && tempB < bSize){
		    if(a[tempA] > b[tempB]){
			    c[tempC++] = b[tempB++];
			}else{
			    c[tempC++] = a[tempA++];
			}
		}
		
		while(tempA < aSize){
		    c[tempC++] = a[tempA++];
		}
		
		while(tempB < bSize){
		    c[tempC++] = b[tempB++];
		}
	}

       這個方法非常簡單,一共有着5個參數(也可以簡化爲3個參數),其中a,b數組是待合併數組,aSize,bSize是數組長度(這兩個參數可以去掉),c爲目標數組。主要的流程就是不斷的比較a,b數組的大小,然後將較小數據複製進c中。這裏面關鍵的一點就是使用了3個臨時變量,用於標誌每個數組對應的位置,這樣子可以極大簡化我們的代碼設計。下面是對應的圖示過程:

       


       有了這個方法之後,我們就可以開始寫歸併排序的主體方法了。寫主體方法也很簡單,思想就是分治算法。

  • 第一步:就是將大數組分成兩個小的數組
  • 第二部:排序這兩個數組,使用的是遞歸排序方法,也就是自己調用自己
  • 第三部:調用上面的合併方法合併起來即可
       代碼非常簡單,直接貼上
public class TowersApp{
    
	public static void main(String[] args){
	    int[] a = {1,1,0,1,1,5,3};
        mergeSort(a);
		
		for(int i=0; i<a.length; i++){
		    System.out.print(a[i]);
		}
	}
	
	
	public static void mergeSort(int[] source){
	    //遞歸出口
		if(source.length == 1) return;
		
		//將大數組分成兩個小數組
		int middle = source.length / 2;
		int[] left = new int[middle];
		for(int i=0; i<middle; i++){
		    left[i] = source[i];
		}
		
		int[] right = new int[source.length - middle];
		for(int i=middle; i<source.length; i++){
		    right[i-middle] = source[i];
		}
		
		//對數據進行排序(這裏使用遞歸排序)
		mergeSort(left);
		mergeSort(right);
		
		//合併排序好的數據
		merge(left, left.length, right, right.length, source);
	}
	
	
	public static void merge(int[] a, int aSize, int[] b, int bSize, int[] c){
		int tempA = 0, tempB = 0, tempC = 0;
		while(tempA < aSize && tempB < bSize){
		    if(a[tempA] > b[tempB]){
			    c[tempC++] = b[tempB++];
			}else{
			    c[tempC++] = a[tempA++];
			}
		}
		
		while(tempA < aSize){
		    c[tempC++] = a[tempA++];
		}
		
		while(tempB < bSize){
		    c[tempC++] = b[tempB++];
		}
	}
}



       總結:要記住歸併排序算法的核心核心思想:分而治之。

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