归并排序是基于分治思想的一种算法,分治的基本步骤为:
1: 分解
2: 求解
3: 合并
- 在分解的时候,归并排序算法每次把序列从序列中点,一分为二,递归不断分解,直到当前序列只有一个元素;
- 求解的过程就是合并的过程,理解了归并排序算法是如何合并的,就明白原因了:
- 合并是两两合并:第一次合并两个子序列都只有一个元素,取较小者暂存在临时数组中,然后把较大者也拷贝到临时数组中,这样我们就完成了第一个第一轮合并;全部第一轮合并结束后,我们得到了若干个长度为2的子序列,这些子序列各自都是有序的;然后进行第二轮合并,合并两个有序子序列,借助临时数组,把元素依次由小到大拷贝到临时数组中,最后再用临时数组去覆盖原数组中相应范围的元素。
- 所以归并排序有O(n)的额外空间消耗。
心得:代码要亲手去调,永远不知道错误会出现在哪里,不调出来永远不会考虑周到。
注:参考了这篇博客,图解归并排序可以看下。
void Merge(vector<int> &arr, int low, int mid, int high){
int i = low, j = mid + 1, k = 0;
vector<int> tmp(high - low + 1, 0);
while(i <= mid && j <= high){
if(arr[i] < arr[j]){
tmp[k++] = arr[i++];
}else{
tmp[k++] = arr[j++];
}
}
while(i <= mid){
tmp[k++] = arr[i++];
}
while(j <= high){
tmp[k++] = arr[j++];
}
for(int x = 0; x < tmp.size(); x++)
arr[low + x] = tmp[x];
cout<<endl;
}
void MergeSort(vector<int> &arr, int low, int high){
if(low < high){
int mid = low + (high - low) / 2;
MergeSort(arr, low, mid); //划分: do nothing
MergeSort(arr, mid + 1, high);
Merge(arr, low, mid, high); //合并
}
return;
}
int main()
{
//...
MergeSort(vec, 0, vec.size()-1);
//...
return 0;
}