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