|基本思路
歸併排序利用了遞歸的思想(而是分而治之的思想),將數組一分爲二,先將左半部分(座標爲0~mid)排好序,再將右半部分排好序(都是調用函數),最後將兩部分合並起來。整體算法時間複雜度爲O(nlogn),空間複雜度爲O(n)。
|歸併排序的c++具體實現
#include<bits/stdc++.h>
using namespace std;
//歸併過程
void merge(int arr[], int l, int mid, int r){
int help[r-l+1];//輔助數組
int i = 0;
int lIndex = l;
int rIndex = mid+1;
while(lIndex <= mid && rIndex <= r){
help[i++] = arr[lIndex] < arr[rIndex] ? arr[lIndex++]:arr[rIndex++];
}
//左邊和右邊肯定有一邊到頭了,不可能同時,因爲每次只移動一邊
while(lIndex <= mid){
help[i++] = arr[lIndex++];
}
while(rIndex <= r){
help[i++] = arr[rIndex++];
}
//將排好序的輔助數組賦值給原始數組,不需要返回值
for(i = 0; i < r-l+1; i++){
arr[l+i] = help[i];
}
}
//遞歸
static void mergeSort(int 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);
}
//歸併排序整個數組
void mergeSort(int arr[], int n){
//如果數組爲空或只有一個元素,不需要排序
if(arr == NULL || n < 2){
return;
}
mergeSort(arr,0,n-1);
}
int main(){
int n;
while(cin >> n){
int arr[n];
for(int i = 0; i < n; i++) cin >> arr[i];
mergeSort(arr, n);
for(int i = 0; i < n; i++){
cout << arr[i] << " ";
}
cout << endl;
}
return 0;
}
|補充:遞歸思想
遞歸過程就是系統輔助你壓棧的過程,保護好現場,以後好繼續。
一個函數調用過程之前,會把自己的所有信息全部壓入棧中,保留現場,子過程返回以後會利用這些信息徹底還原現場繼續跑,跑完之後再從棧中拿出一個函數再還原現場,最終串起來所有子過程和父過程。
遞歸過程分析時間複雜度:(看是否滿足master方程)
T(N) = aT(N/b) + O(N^d)
N是原始問題的樣本量,a是子過程的發生次數,N/b是子過程的樣本量,O(N^d)是除子過程調用外剩下的過程。
log(b,a) > d ----------> O(N^log(b,a))
log(b,a) = d ----------> O(N^d*logN)
log(b,a) < d -----------> O(N^d)
感謝左神的講解,終於記住了遞歸排序的具體實現步驟!!自己實現的過程中發現一些細節需要注意,不然總是出錯,尤其是要注意邊界。遞歸的思想左神也講得超棒!爲左神打電話!(人還帥哈哈哈)繼續加油吧ヾ(◍°∇°◍)ノ゙