基本思想
“归并”的含义就是将两个或两个以上的有序表组合成一个新的有序表。
下面的示意图来自博客图解排序算法(四)之归并排序
代码:(递归版本)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <bits/stdc++.h>
using namespace std;
void Merge(vector<int>&num, int left, int mid, int right)
{
vector<int>a(num.begin(), num.end()); //开辟一个辅助数组,并将待排序的数组赋值给新开辟的数组
int i, j, k;
for(i=left, j = mid+1, k = left; i<=mid && j<=right; k++)
{
if(a[i] > a[j]) // 比较 a 的左右两段中的元素,
num[k] = a[j++]; // 将较小者复制到num中,
else
num[k] = a[i++];
}
// 下面的两个 while 循环只会执行其中的一个。
while(i <= mid)
num[k++] = a[i++]; //若第一个表没有检测完,则复制
while(j <= right)
num[k++] = a[j++];//若第二个表没有检测完,则复制
}
void MergeSort(vector<int>&num, int left, int right)
{
if(left < right)
{
int mid = ((right - left) >> 1) + left;
MergeSort(num, left, mid);
MergeSort(num, mid+1, right);
Merge(num, left, mid, right);
}
}
int main()
{
int numbers[] = {53, 17, 78, 9, 45, 65, 87, 32};
vector<int>num(numbers, numbers+8);
cout<<"数组的原来序列为:";
vector<int>::iterator it = num.begin();
for(it = num.begin(); it != num.end(); it++)
cout<< *it <<' ';
cout<< endl<<endl;
// 归排序
MergeSort(num, 0, num.size()-1);
cout <<"经过归并排序后,数组变为: ";
for(it = num.begin(); it != num.end(); it++)
cout<< *it <<' ';
cout<< endl;
return 0;
}
代码:迭代版本
#include <iostream>
#include <cstdio>
#include <cstring>
#include <bits/stdc++.h>
using namespace std;
void MergeSort(vector<int>&num, int n)
{
int i, next, left_min, right_min, left_max, right_max;
// i 用于 for 循环迭代,temp 用来存储临时数组,
vector<int>temp(num.begin(), num.end());
// i 是步长,第一次是1个元素与1个元素相比,第2个是两个元素与2个元素相比
for(i = 1; i<n; i *= 2)
{
// left_min 最后是要小于 n-i 的,这一点可以通过画图得到
// left_min = right_max 是指上一组排序完成之后,将上一组的 right_max 赋值给下一组的 left_min
for(left_min=0; left_min < n-i; left_min = right_max)
{
right_min = left_max = left_min + i;
right_max = right_min + i;
next = 0;
if(right_max > n) // 因为奇数的数组最后很有可能 right_max > n,所以将它限制到最大为 n
right_max = n;
// 在这里跟递归中的归并操是一样的,从两个数组中取小的出来放入临时数组
while(left_min < left_max && right_min < right_max)
{
if(num[left_min] < num[right_min])
{
temp[next++] = num[left_min++];
}
else
temp[next++] = num[right_min++];
}
// 但是上面的过程并不会同时将左右两个数组的元素都放入临时存储数组 temp 中
// 要么左边会剩一点,要么右边会剩一点,所以这个时候要对剩余的进行操作
// 如果左边剩了,说明这些应该是最大的,应该放在数组的右边
while(left_min < left_max)
{
num[--right_min] = num[--left_max];
}
// 将临时存储的元素放入数组中得到最后的结果
while(next>0)//如果最后是右边数组有剩余,那么num数组中在right_min 和right_max 之间的数就不需要动了,因为他们是左右数组比较交换时是最大的。
num[--right_min] = temp[--next];
}
}
}
int main()
{
int numbers[] = {53, 17, 78, 9, 45, 65, 87, 32};
vector<int>num(numbers, numbers+8);
cout<<"数组的原来序列为:";
vector<int>::iterator it = num.begin();
for(it = num.begin(); it != num.end(); it++)
cout<< *it <<' ';
cout<< endl<<endl;
// 归排序
MergeSort(num, num.size());
cout <<"经过归并排序后,数组变为: ";
for(it = num.begin(); it != num.end(); it++)
cout<< *it <<' ';
cout<< endl;
return 0;
}