輸入:先輸入進行合併排序元素的個數,然後依次隨機輸入(或隨機生成)每個數字。
輸出:元素排序後的結果,數字之間不加任何標識符。
示例:輸入:8 11 1 2 4 8 6 15 8,輸出:1 2 4 6 8 8 11 15
#include<iostream>
using namespace std;
//合併排序/歸併排序
template<typename T>
void __mergeSort(T arr[], int l, int mid, int r)
{
// 經測試,傳遞aux數組的性能效果並不好
//T aux[r - l + 1];
T *aux = new T[r - l + 1];
for (int i = l; i <= r; i++)
aux[i - l] = arr[i];//賦值
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;
}
template<typename T>
void MergeSort(T arr[], int l, int r)
{
if (l >= r)
{
return;
}
int mid = (r + l) / 2;
MergeSort(arr, l, mid);//先將這個運行到底 ①
MergeSort(arr, mid + 1, r);//這個,mid不是那個例如數組大小爲6,mid=3那個mid,而是上步①結束時的mid
__mergeSort(arr, l, mid, r);//這個排序,排的是第一對(1邊1個),在排第二對。。。然後下一輪第一對(1邊2個)相排.。。
}
int main()
{
int n;
cin >> n;
int *arr = new int[n];
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
MergeSort(arr, 0, n-1);
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
delete[]arr;
return 0;
}
--------------------------------------------------------------------------
優化:
#include<iostream>
using namespace std;
//合併排序/歸併排序
template<typename T>
void __mergeSort(T arr[], int l, int mid, int r)
{
// 經測試,傳遞aux數組的性能效果並不好
//T aux[r - l + 1];
T *aux = new T[r - l + 1];
for (int i = l; i <= r; i++)
aux[i - l] = arr[i];//賦值
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;
}
template<typename T>
void MergeSort(T arr[], int l, int r)
{
if (l >= r)
{
return;
}
//優化1:
/*if (r - l <= 15)//由於小數量的排序,插入排序比歸併更划算,所以這選擇這樣,這個數是測試得到的,不一定是15
{
insertionSort1(arr, l, r);
}*/
int mid = (r + l) / 2;
MergeSort(arr, l, mid);//先將這個運行到底 ①
MergeSort(arr, mid + 1, r);//這個,mid不是那個例如數組大小爲6,mid=3那個mid,而是上步①結束時的mid
__mergeSort(arr, l, mid, r);
//優化2:
/*
if(arr[mid] > arr[mid + 1])//例如這裏第一次是1個和1個比,比完後,兩個元素(數組A)和兩個元素(數組B)比,這兩個數組裏的元素是已經排好序的,所以只需要比較arr[mid] 和 arr[mid + 1]就知道還需不需要去比較;
{
__mergeSort(arr, l, mid, r);//這個排序,排的是第一對(1邊1個),在排第二對。。。然後下一輪第一對(1邊2個)相排.。。
}
*/
}
int main()
{
int n;
cin >> n;
int *arr = new int[n];
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
MergeSort(arr, 0, n-1);
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
delete[]arr;
return 0;
}
//非遞歸
自底向上: 迭代的方式
template <typename T>
void mergeSortBU(T arr[], int n){
for( int sz = 1; sz <= n ; sz += sz )//一次加sz,(下面的循環,sz每加一次sz,下面的數組A和數組B就會擴大1倍)
for( int i = 0 ; i+size < n ; i += sz+sz )//排序用的,第一次排第一對(數組A和數組B),然後第二對...第三對...//i+size < n 是爲了防止下面中間的元素的越界
// 對 arr[i...i+sz-1] 和 arr[i+sz...i+2*sz-1] 進行歸併
__merge(arr, i, i+sz-1, min(i+sz+sz-1,n-1) );// min(i+sz+sz-1,n-1)由於最右邊的元素可能超過界限,所以用min()就可以起到一個限制作用
}
//非遞歸的優化
for( int i = 0 ; i < n ; i += 16 )
insertionSort(arr,i,min(i+15,n-1));
for( int sz = 16; sz <= n ; sz += sz )
for( int i = 0 ; i < n - sz ; i += sz+sz )
if( arr[i+sz-1] > arr[i+sz] )
__merge(arr, i, i+sz-1, min(i+sz+sz-1,n-1) );