介紹
歸并排序(MERGE-SORT)是建立在歸并操作上的一種有效的排序演算法,該演算法是采用分治法(Divide and Conquer)的一個非常典型的應用,
將已有序的子序列合并,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序,
若將兩個有序表合并成一個有序表,稱為二路歸并,歸并排序是一種穩定的排序方法,
占記憶體;
步驟
1. 申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合并后的序列;
2. 設定兩個指標,最初位置分別為兩個已經排序序列的起始位置;
3. 比較兩個指標所指向的元素,選擇相對小的元素放入到合并空間,并移動指標到下一位置;
4. 重復步驟3直到某一指標超出序列尾;
5. 將另一序列剩下的所有元素直接復制到合并序列尾
代碼
private static void MergeConsole(string location, int[] arr) { Console.Write($"{location}: "); foreach (var i in arr) { Console.Write("{0}\t", i); } Console.WriteLine(); } /// <summary> /// 歸并陣列 /// </summary> /// <param name="arr">要歸并的陣列</param> /// <param name="left">歸并左序列首元素下標</param> /// <param name="mid">拆分元素的下標</param> /// <param name="right">歸并右序列最后元素下標</param> private static void MergeArray(int[] arr, int left, int mid, int right) { int[] temp = new int[right - left + 1]; int m = left, n = mid + 1, k = 0; while (n <= right && m <= mid) { if (arr[m] > arr[n]) { temp[k++] = arr[n++]; } else { temp[k++] = arr[m++]; } } while (n < right + 1) { temp[k++] = arr[n++]; } while (m < mid + 1) { temp[k++] = arr[m++]; } for (k = 0, m = left; m < right + 1; k++, m++) { arr[m] = temp[k]; } } /// <summary> /// 歸并排序 /// </summary> /// <param name="arr">要歸并的陣列</param> /// <param name="left">歸并左序列首元素下標</param> /// <param name="right">歸并右序列最后元素下標</param> public static void MergeSort(int[] arr, int left, int right) { if (left < right) { int mid = (left + right) / 2; MergeSort(arr, left, mid); MergeConsole("_left: ", arr); MergeSort(arr, mid + 1, right); MergeConsole("right: ", arr); MergeArray(arr, left, mid, right); MergeConsole("merge: ", arr); Console.WriteLine(); } } static void Main(string[] args) { int[] array = { 149, 100, 112, 38, 80, 35, 615, 297, 592, 976, 143, 217 }; MergeSort(array, 0, array.Length - 1); Console.ReadLine(); }View Code
性能分析
1. 時間復雜度:O(n log n),最好、最壞、平均時間復雜度都是一樣的,因為不關心要排序的陣列初始狀態;
2. 空間復雜度:O(n),在任意時刻只有一個函式執行,只有一個臨時的記憶體空間在使用;
3. 穩定性: 穩定;相同的值可以選擇是放在左邊還是右邊的,
本文地址:https://www.cnblogs.com/Fletcher/p/11833968.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/125570.html
標籤:其他
