归并排序(MergeSort)思想与实现

  归并排序属于高级的排序方法,在介绍归并排序的思想之前,先讲述一种采用比较方式的排序方法。假设有两个已经排好序的数组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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值