归并排序属于高级的排序方法,在介绍归并排序的思想之前,先讲述一种采用比较方式的排序方法。假设有两个已经排好序的数组arr1[ ],arr2[ ],且均是升序或者降序,那么可以进行以下操作:以升序为例,先创建一个尺寸大小为arr1[ ]与arr2[ ]尺寸之和的数组temp[ ],然后同时从两数组的第0个元素开始遍历,若arr1[i] < arr2[j],则可以把arr1[i]放入temp[k]中后,执行i++,k++,继续往后比较;若arr1[i] > arr2[j],则可以把arr2[j]放入temp[k]中后,执行j++,k++,继续往后比较;最终直到把两个数组中的所有元素放入数组temp[ ]中。
总结地说,这种比较方式的排序方法思想就是:因为两个数组都是有序的(假设为升序),故两个数组自身的后一个元素肯定不小于前一个元素,所以当两个数组分别从头开始遍历时,只要发现本数组的当前元素比另一个数组的当前元素小,那么该元素肯定为目前两数组中最小的元素。
归并排序就是用到的这种方法,接下来讲述一下归并排序的思想。
(1) 归并排序的思想
归并排序的思想就是:首先将原始数组对半切分,然后将所切成的两个子数组再次切分,直到所切分的子数组只有1个元素为止;在此基础上,先创建一个临时数组,再将最后只有1个元素的子数组进行排序,排完序之后将所切成的两个子数组进行合并到临时数组中,合并的方法为本文开头所描述的方法,最后将临时数组中的值再重新赋值到原始数组对应的位置中;之后,再返回最终切分操作之前的切分操作,并做相同的操作,对两子数组进行合并;以此类推,直到返回到原始数组所切分成两个子数组为止,并最终合并成有序的数组。所以,该方法采用递归方法比较简单,本文是算法实现也采用递归的方法。
为了更好地理解该排序算法,我们来看以下图片:
从上图可知,原始数组为:1 8 6 4 10 5 3 2 22,以排升序为例,接下来进行分步操作。
第一步:首先将原始数组对半切分,切分成左右两个子数组,再将左右两个子数组对半切分;以此类推,最终切分成如下各子数组:{1},{8},{6},{4},{10},{3},{5},{2},{22}。
第二步:将{1},{8}合并成{1,8},再将{1,8},{6}合并成{1,6,8};将{4},{10}合并成{4,10};将{3},{5}合并成{3,5};将{2},{22}合并成{2,22}。
第三步:将{1,6,8},{4,10}合并成{1,4,6,8,10};将{3,5},{2,22}合并成{2,3,5,22}。
第四步:将{1,4,6,8,10},{2,3,5,22}合并成{1,2,3,4,5,6,8,10,22}。
(2) 归并排序的实现
本次排序算法采用C++模版编程来实现,并采用了递归的方法。
#include <iostream>
#include <iterator>
#include <algorithm>
using namespace std;
template<class T,size_t N>
void PrintArr(T (&arr)[N])
{
copy(arr,arr+N,ostream_iterator<T>(cout," "));
cout << endl;
}
template<class T,size_t N>
void MergeSort(T (&arr)[N],size_t start = 0,ssize_t end = (N-1))
{
size_t size = end + 1 -start;
if(size <= 1) {
return;
}
if(size == 2) {
if(arr[start] > arr[end]) {
swap(arr[start],arr[end]);
}
return;
}
ssize_t mid = size/2;
MergeSort(arr,start,start+mid-1);
MergeSort(arr,start+mid,end);
size_t i(start),j(start+mid),k(0);
T temp[size];
while(i < (start+mid) or j <= end) {
if(arr[i] <= arr[j] and i < (start+mid) or j == (end+1)) {
temp[k] = arr[i];
k++;
i++;
} else if(arr[j] <= arr[i] and j <=end or i == (start+mid)) {
temp[k]= arr[j];
k++;
j++;
}
}
i = start;
k = 0;
while(i <= end ) {
arr[i] = temp[k];
i++;
k++;
}
PrintArr(arr);
return;
}
int main()
{
int arr[]= {1,8,6,4,10,5,3,2,22};
// int arr[]= {1,4,5,2,4,8,9,10,22,4,6,1,8,9,1,21,34,54,2,4};
cout << "The init:" << endl;
PrintArr(arr);
cout << "The sort:" << endl;
MergeSort(arr);
PrintArr(arr);
cout << "The final:" << endl;
PrintArr(arr);
}
原始数组为:1 8 6 4 10 5 3 2 22
程序运行结果为:1 2 3 4 5 6 8 10 22