歸並排序
歸並排序是建立在歸並操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer) 的一個典型的應用。
將已有序的字序列合並,得到完全有序的序列;即先使得每個字序列有序,再使子序列段間有序。若將兩個有序表合並成一個有序表,成為2-路歸並排序。
算法描述:
1、把長度為n的輸入序列分成兩個長度為n/2的字序列;
2、對這兩個子序列分別采用歸並排序
3、將兩個排序好的字序列合並成一個最終的排序序列。
優劣分析:
歸並排序是一種穩定的排序算法。和選擇排序一樣,歸並排序性能不受輸入數據的影響,但表現比選擇排序好的多,因為始終都是O(nlogn)的時間復雜度。
代價是需要額外的內存空間。
1、 歸並排序采用了分治的思想,它的核心在於合並子問題而不是求解子問題。【快速排序也采用了分治思想,但它的核心是在於求解子問題而不需要合並子問題的解】
2、歸並排序不是原地址排序,它的排序過程需要借助額外的內存空間。
3、歸並排序是穩定排序(其實,還要看具體代碼怎么寫,如果兩個數的值相等,不保持原順序就會變成非穩定的了)
4、歸並排序的時間復雜度為O(NlogN)
/* MergeSort_hpp */
#ifndef MergeSort_hpp
#define MergeSort_hpp
#include <stdio.h>
#include <vector>
using namespace std;
class MergeSort {
public:
void sort(vector<int>& arr, int len);
};
#endif /* MergeSort_hpp */
#include "MergeSort.hpp"
void subSort(vector<int>& arr, int left, int right, vector<int>& temp);
void merge(vector<int>& arr, int left, int mid, int right, vector<int>& temp);
void MergeSort::sort(vector<int>& arr, int len) {
if (len < 2) {
return;
}
vector<int> temp(arr);//這里是做了優化,在遞歸方法外面創建一個專門用於存放每次遞歸是存放臨時有序子數組的數組
subSort(arr, 0, int(len-1), temp);
}
void subSort(vector<int>& arr, int left, int right, vector<int>& temp){
if (left < right) {
int mid = (left + right)/2;
subSort(arr, left, mid, temp);//左序列歸並排序,使得左序列有序
subSort(arr, mid+1, right, temp);//右序列歸並排序,使得右序列有序
merge(arr, left, mid, right, temp);//將兩個有序子數組做合並操作
}
}
/*MergeSort.cpp*/
void merge(vector<int>& arr, int left, int mid, int right, vector<int>& temp){
int i = left;//左序列指針
int j = mid + 1;//有序列指針
int p = 0;//臨時數組指針
while (i <= mid && j <= right) {
if (arr[i] <= arr[j]) {
temp[p++] = arr[i++];
}else {
temp[p++] = arr[j++];
}
}
//將左邊剩余元素填充到temp中
while (i <= mid) {
temp[p++] = arr[i++];
}
//將右序列剩余元素填充進temp
while (j <= right) {
temp[p++] = arr[j++];
}
p = 0;
//將temp中的元素全部拷貝到原數組中
while(left <= right) {
arr[left++] = temp[p++];
}
}
/*main*/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, const char * argv[]) {
vector<int> arr4= {7, 5, 3, 2, 4, 9, 1, 8, 6, 0};
cout << "arr4: " << endl;
for (int i = 0; i < 10 ; i++) {
cout << arr4[i] <<" ";
}
cout << endl;
MergeSort mergeSort = MergeSort();
mergeSort.sort(arr4, 10);
cout << "merge sorted arr4: " << endl;
for (int item : arr4) {
cout << item <<" ";
}
cout << endl;
}
控制台輸出結果
//bash
arr4:
7 5 3 2 4 9 1 8 6 0
merge sorted arr4:
0 1 2 3 4 5 6 7 8 9
Program ended with exit code: 0