歸併排序(Merge sort),是創建在歸併操作上的一種有效的排序算法,效率爲O(nlog n)。該算法是採用分治法(Divide and Conquer)的一個非常典型的應用,且各層分治遞歸可以同時進行。
一、算法基本思想
(1)基本思想
歸併排序的基本思想就是:把待排序序列分爲若干個子序列,每個子序列是有序的,然後再把有序子序列合併爲整體有序序列。經常被使用的是二路歸併算法,即將兩個已經排序的序列合併成一個序列的操作。
(2)運行過程
歸併排序算法的運行過程如下:
1、申請空間,使其大小爲兩個已經排序序列之和,該空間用來存放合併後的序列;
2、設定兩個指針,最初位置分別爲兩個已經排序序列的起始位置;
3、比較兩個指針所指向的元素,選擇相對小的元素放入到合併空間,並移動指針到下一位置;
4、重複步驟3直到某一指針達到序列尾;
5、將另一序列剩下的所有元素直接複製到合併序列尾。
(3)示例
二、算法實現(核心代碼)
C++實現:
template<typename T> //整數或浮點數皆可使用 void merge_sort(T arr[], int len) { T* a = arr; T* b = new T[len]; for (int seg = 1; seg < len; seg += seg) { for (int start = 0; start < len; start += seg + seg) { int low = start, mid = min(start + seg, len), high = min(start + seg + seg, len); int k = low; int start1 = low, end1 = mid; int start2 = mid, end2 = high; while (start1 < end1 && start2 < end2) b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++]; while (start1 < end1) b[k++] = a[start1++]; while (start2 < end2) b[k++] = a[start2++]; } T* temp = a; a = b; b = temp; } if (a != arr) { for (int i = 0; i < len; i++) b[i] = a[i]; b = a; } delete[] b; }
Java實現:
三、性能(算法時間、空間複雜度、穩定性)分析
public void merge_sort(int[] arr) { int len = arr.length; int[] result = new int[len]; int block, start; for(block = 1; block < len ; block *= 2) { for(start = 0; start <len; start += 2 * block) { int low = start; int mid = (start + block) < len ? (start + block) : len; int high = (start + 2 * block) < len ? (start + 2 * block) : len; //兩個塊的起始下標及結束下標 int start1 = low, end1 = mid; int start2 = mid, end2 = high; //開始對兩個block進行歸併排序 while (start1 < end1 && start2 < end2) { result[low++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++]; } while(start1 < end1) { result[low++] = arr[start1++]; } while(start2 < end2) { result[low++] = arr[start2++]; } } int[] temp = arr; arr = result; result = temp; } result = arr; }
歸併排序的時間複雜度爲O(nlogn);空間複雜度爲O(n);是穩定的排序算法。
歸併排序速度僅次於快速排序,爲穩定排序算法。一般用於對總體無序,但是各子項相對有序的數列效果比較好。