歸併排序的基本思想:
將兩個或兩個以上的有序子序列”歸併”爲一個有序序列:假定待排序表含有n個記錄, 則可以看成是n個有序的子表, 每個子表長度爲1, 然後兩兩歸併, 得到[n/2]個長度爲2或1的有序表,; 再量量歸併, ...., 如此重複, 直到合併成爲一個長度爲n的有序表爲止, 這種排序方法稱爲2-路歸併排序.如圖爲一個2-路歸併排序的一個示例:
- /**說明:
- 將有序的記錄序列 initList[left:mid] 和 initList[mid+1:right]歸併爲有序的記錄序列 initList[left:right]
- initList: 原始的有序序列[分爲兩段]
- tmpList: 合併過程中需要的中間序列
- left: initList最左邊元素的下標
- mid: 指向第一個有序序列的最後一個元素的下標
- right: initList最右邊元素的下標
- */
- template <typename Type>
- int Merge(Type *initList, Type *tmpList, int left, int mid, int right)
- {
- //先將待歸併的數組複製到tmpList中去
- std::copy(initList+left, initList+right+1, tmpList+left);
- // 同下:
- // for (int i = left; i <= right; ++i)
- // {
- // tmpList[i] = initList[i];
- // }
- int s1 = left, s2 = mid+1;
- int iResult = left;
- while (s1 <= mid && s2 <= right)
- {
- if (tmpList[s1] <= tmpList[s2])
- {
- initList[iResult ++] = tmpList[s1 ++];
- }
- else
- {
- initList[iResult ++] = tmpList[s2 ++];
- }
- }
- int *end;
- if (s1 <= mid)
- end = std::copy(tmpList+s1, tmpList+mid+1, initList+iResult);
- if (s2 <= right)
- end = std::copy(tmpList+s2, tmpList+right+1, initList+iResult);
- return end - (initList+left);
- // 同下:其實這兩個循環只有一個會執行
- // while (s1 <= mid)
- // {
- // initList[iResult ++] = tmpList[s1 ++];
- // }
- // while (s2 <= right)
- // {
- // initList[iResult ++] = tmpList[s2 ++];
- // }
- //
- // return iResult;
- }
- //二路歸併排序-遞歸算法
- template <typename Type>
- void mergeSort(Type *initList, Type *tmpList, int left, int right)
- {
- if (left >= right)
- return;
- int mid = (left+right)/2;
- mergeSort(initList, tmpList, left, mid); //先將左邊元素排序
- mergeSort(initList, tmpList, mid+1, right); //後將右邊元素排序
- Merge(initList, tmpList, left, mid, right); //合併
- }
可以看出對n個記錄進行歸併排序的時間複雜度爲Ο(nlogn)。即:
(1)每一趟歸併(合併)的時間複雜度爲 O(n);
(2)總共需進行[logn]趟。
原文地址:http://blog.csdn.net/zjf280441589/article/details/42366865