代码改变世界

归并排序(MergeSort)

2014-01-03 12:50  江湖么名  阅读(244)  评论(0编辑  收藏  举报

原帖:http://blog.csdn.net/magicharvey/article/details/10192933

算法描述

归并排序(MergeSort)是采用分治法的一个非常典型的应用。通过先递的分解数组,再合数组就完成了归并排序。


基本思想

归并排序是将整个集合问题分解成最小单元,将该单元内的元素全部排序,然后将相邻的单元重新排序。如果将n1,n2看做一个整体n的话,则针对n,先对其一半进行排序,另一半排序,然后整体再次排序。


实现步骤

  1. 递归的将数组分为两个子数组,每个子数组重新分为两个子数组,直到数组个数为1为止;
  2. 将相邻的两个有序数组合并为一个有序数组;
  3. 最终直到剩下两个有序子数组,将其合并为一个总的有序大数组。

算法实现

代码在xcode中验证,可以直接使用
//新建一个临时数组,用来存放排序好的元素
int temp[100] = {0};

//交换两个值的函数
void swap(int a, int b)
{
    int index = a;
    a = b;
    b = index;
}

//将两个有序的序列a[begin ... mid]和a[mid+1...end]合并
void M_Sort(int a[], int begin, int mid, int end)
{
    int i = begin;  //左边数组的开始节点
    int j = mid+1;  //右边数组的开始节点
    int k = 0;      //合并后的数组的下标
    
    //左边或者右边数组是否有一个读取完毕
    while(i <= mid && j <= end)
    {
        if( a[i] <= a[j])
        {
            temp[k++] = a[i++];
        }
        else
        {
            temp[k++] = a[j++];
        }
    }
    
    //将左边或者右边节点剩余的节点复制给临时数组
    while(i <= mid)
    {
        temp[k++] = a[i++];
    }
    while(j <= end)
    {
        temp[k++] = a[j++];
    }
    
    //k代表合并后的数组的大小
    for(int m = 0; m < k; m++)
    {
        a[begin+m] = temp[m];   //begin+m代表在a数组中的位置
    }
}

//将序列a[begin ... end]不断地分为相同的两个子序列,直到序列中的元素个数为1为止,不断递归
void MergeSort(int a[], int begin, int end)
{
    if(begin<end)
    {
        int mid = (begin + end )/2 ;
        MergeSort(a, begin, mid);   //递归左边的序列
        MergeSort(a, mid+1, end);   //递归右边的序列
        M_Sort(a, begin, mid ,end); //合并左右的序列
    }
}

性能分析

归并算法是又分割和归并两部分组成的。对于分割部分,如果我们使用二分查找的话,时间是O(logn),在最后归并的时候,时间是O(n),所以总的时间O(nlogn)。

归并排序是稳定的,它的最差,平均,最好时间都是O(nlogn)。但是它需要额外的存储空间,这在某些内存紧张的机器上会受到限制。