1. 程式人生 > >遞迴應用之歸併排序

遞迴應用之歸併排序

演算法分析
        歸併排序是建立在歸併操作上的一種有效的排序演算法,該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱為二路歸併。
基本思路:
        先遞迴的把陣列劃分為兩個子陣列,一直遞迴到陣列中只有一個元素,然後再呼叫函式把兩個子陣列排好序,因為該函式在遞迴劃分陣列時會被壓入棧,所以這個函式真正的作用是對兩個有序的子陣列進行排序;
基本步驟:
        1、判斷引數的有效性,也就是遞迴的出口;
        2、首先什麼都不管,直接把陣列平分成兩個子陣列;
        3、遞迴呼叫劃分陣列函式,最後劃分到陣列中只有一個元素,這也意味著陣列是有序的了;
        4、然後呼叫排序函式,把兩個有序的數組合併成一個有序的陣列;

        5、排序函式的步驟,讓兩個陣列的元素進行比較,把大的/小的元素存放到臨時陣列中,如果有一個數組的元素被取光了,那就直接把另一陣列的元素放到臨時陣列中,然後把臨時陣列中的元素都複製到實際的陣列中;

示例程式碼:

public class GuibingSort {
	//first陣列初始索引值,mid陣列分界點索引,last陣列結束索引,temp[]臨時陣列
	//以mid為界限,將a分為兩個陣列,對其進行歸併排序
	//將二個有序數列合併。這個非常簡單,只要從比較二個數列的第一個數,
	//誰小就先取誰,取了後就在對應數列中取下一個數。然後再進行比較,
	//如果有數列遍歷完畢,那直接將另一個數列的資料依次取出即可。
	void mergearray(int a[], int first, int mid, int last, int temp[])
	{//兩個有序陣列的歸併
		int i = first,m = mid;//第一個陣列的範圍
		int j = mid + 1,n = last;//第二個陣列的範圍
		int k = 0;//temp的初始下標
		
		while (i <= m && j <= n)//分別從兩個陣列中取值
		{
			if (a[i] <= a[j])//取較小的數放到temp陣列中
				temp[k++] = a[i++];//先進行賦值運算,然後k,i自加1
			//注意,這裡j並沒有變化,下一次比較仍然是上一次的j值,直到else發生
			else
				temp[k++] = a[j++];//j變化,i不變化
		}
		
		while (i <= m)//如果陣列中仍有元素,直接複製到temp後面即可
			temp[k++] = a[i++];
		
		while (j <= n)
			temp[k++] = a[j++];
		
		for (i = 0; i < k; i++)//將排好序的陣列重新賦給a
			a[first + i] = temp[i];
	}
	void mergesort(int a[], int first, int last, int temp[])
	//a[]是需要排序的陣列,first, last是索引範圍
	{
		if (first < last)//當陣列中只有一個元素時,first==last,遞迴結束
		{
			int mid = (first + last) / 2;
			mergesort(a, first, mid, temp);    //左邊遞迴,直到只剩一個元素
			mergesort(a, mid + 1, last, temp); //右邊遞迴,直到只剩一個元素
			mergearray(a, first, mid, last, temp); //再將二個有序數列合併
		}
	}
	public void sort(int[] a) {
		int n=a.length;
		int[] b=new int[n];
		mergesort(a, 0, n-1, b);
	}
public static void main(String[] args) {
	int[] a= {10,9,8,7,6,5,4,3};
	GuibingSort guibingSort=new GuibingSort();
	guibingSort.sort(a);
	for (int i : a) {
		System.out.println(i);
	}
}
}
執行過程解釋:

第一次歸併10和9,排序結果9,10

第二次歸併8和7,排序結果7,8

第三次歸併9,10和7,8,,排序結果7,8,9,10

對於6,5,4,3排序過程與上述類似,排序結果為3,4,5,6

最後歸併兩大部分,得到最終結果。