一、介紹:
歸併排序(Merge_Sort)是建立在歸併操作上的一種有效的排序演算法,該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。
二、邏輯:
具體邏輯:分為兩個步驟
1.切分操作:將一組陣列切分成兩部分,運用分治思想(具體實現:遞迴),將切分的兩部分分別進行切分(再次將每部分一分為二),以此類推,直到陣列中的元素不能再進行切分(遞迴到底,直到切分到元素自身”l>=r”)。
2.歸併操作:然後將元素進行比較再依次歸併。
例子:陣列{5,3,2,1,7,4,8,0}進行排序
切分:
1.將陣列分為{5, 3, 2,1}和{,7, 4 ,8, 0}兩個陣列
2.將{5, 3, 2,1}和{7, 4 ,8, 0}兩個陣列分別進行切分,分為{5, 3}、{2, 1}、{7, 4}和{8, 0}
3.將5, 3}、{2, 1}、{7, 4}和{8, 0}陣列再進行分……
4.遞迴到{5}(此時不能分)最後
歸併
1.將5, 3}、{2, 1}、{7, 4}和{8, 0}陣列進行比較,得:{3, 5}、{1, 2}、{4, 7}和{0, 8}
2.將陣列3, 5}、{1, 2}和{4, 7}, {0, 8}中元素進行比較並歸併成{1, 2, 3, 5}和{0, 4, 7, 8}
3.重複”2”操作,最終排序完成,得出{0, 1, 2, 3, 4, 5, 7, 8}
三、程式碼實現
#include <iostream>
using namespace std;
// 將arr[l...mid]和arr[mid+1...r]兩部分進行歸併
template<typename T> //使用模板
void __merge(T arr[], int l, int mid, int r){
//* 這裡需要使用new申請空間, 不要忘了在__merge函式的最後, delete掉申請的空間:)
T aux[r-l+1];
//T *aux = new T[r-l+1];
for( int i = l ; i <= r; i ++ )
aux[i-l] = arr[i];
// 初始化,i指向左半部分的起始索引位置l;j指向右半部分起始索引位置mid+1
int i = l, j = mid+1;
for( int k = l ; k <= r; k ++ ){
if( i > mid ){ // 如果左半部分元素已經全部處理完畢
arr[k] = aux[j-l]; j ++;
}
else if( j > r ){ // 如果右半部分元素已經全部處理完畢
arr[k] = aux[i-l]; i ++;
}
else if( aux[i-l] < aux[j-l] ) { // 左半部分所指元素 < 右半部分所指元素
arr[k] = aux[i-l]; i ++;
}
else{ // 左半部分所指元素 >= 右半部分所指元素
arr[k] = aux[j-l]; j ++;
}
}
//delete[] aux;
}
// 遞迴使用歸併排序,對arr[l...r]的範圍進行排序
template<typename T>
void __mergeSort(T arr[], int l, int r){
if( l >= r )
return;
int mid = (l+r)/2; //將陣列進行切分
__mergeSort(arr, l, mid);
__mergeSort(arr, mid+1, r);
__merge(arr, l, mid, r);
}
template<typename T>
void mergeSort(T arr[], int n){
__mergeSort( arr , 0 , n-1 );
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結