zoukankan      html  css  js  c++  java
  • 归并排序法

    归并排序法,这里介绍二路归并排序法,其他原理类似,只是更加复杂。

    归并排序(Merge Sort)是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列。

    归并排序的具体做法:

    1. 把原序列不断地递归等分,直至每等份只有一个元素,此时每等份都是有序的。
    2. 相邻等份合并,不断合并,直至合并完全。

    二路归并

    归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序最常用的是二路归并,即把两个小的有序的序列和并成一个大的有序序列:合二为一。

    一个二路归并的流程图是这样的:

    多路归并无非是多个有序的小序列合并成一个大的有序序列,道理和二路归并一样。

    把两个有序序列合成一个大的有序序列的实现代码如下:

    void MergeSort(int* a,int* b,int na,int nb,int* c)
    {
        if(a == NULL || na <= 0 || b == NULL || nb <= 0)
            return;
        int i=0,j=0,k=0;
        //将a和b数组中的元素有序的放入到c数组中
        while(i<na && j<na)
        {
            if(a[i]<=b[j])
                c[k++] = a[i++];
            else
                c[k++] = b[j++];
        }
        
        //将剩下的元素全都放入到c数组中
        while(i<na)
            c[k++] = a[i++];
        while(i<nb)
            c[k++] = b[j++];
        
    }

    可以看出,二路归并的时间复杂度是O(n),n是原序列的数据规模。以上代码是归并排序的基础,弄懂了它,就很好写归并排序了,看下归并排序的流程图:

    可以看出,上半部分不断地递归深入:不断地均分原序列,直到每一部分只含有一个元素。下半部分,开始递归返回,通过反复调用二路归并算法,把相邻的有序子序列合并成一个规模更大的序列。

    归并排序的代码如下:

    //把[first,mid]与[mid+1,last]范围内的数据合并
    void mergeArray(int* a,int* b,int first,int mid,int last)
    {
        int i = first;
        int j = mid + 1;
        int k = 0;
        while(i<=mid && j<=last)
        {
            //将[first,mid]与[mid+1,last]内的数据排序合并
            while(i<=mid && a[i]<=a[j])
                b[k++] = a[i++];
            while(j<=last && a[j]<a[i])
                b[k++] = a[j++];
            
            //将剩下的a的数组元素放入到b中
            while(i<=mid)
                b[k++] = a[i++];
            while(j<=last)
                b[k++] = a[j++];
        }
        //将合并后的数组返回到a数组上
        for(int i=0;i<k;i++)
            a[first+i] = b[i];
        
    }
    
    //归并排序
    void mergesort(int* a,int* b,int first,int last)
    {
        if(first < last)
        {
            int mid = first + (last-first)>>1; //求区间中点
            //不断的划分区间,然后进行递归操作
            mergesort(a,b,first,mid); 
            mergesort(a,b,mid+1,last);
            mergeArray(a,b,first,mid,last);
        }
    }
    
    //传入需要归并排序的数组
    void MergeSort(int* a,int n) 
    {
        if(a == NULL && n <= 1)
            return;
        int b[n];
        mergesort(a,b,0,n-1); 
        delete[] b;
    }

    归并排序参考:http://blog.csdn.net/zhangxiangdavaid/article/details/34463409

  • 相关阅读:
    poj 3068 Bridge Across Islands
    XidianOJ 1086 Flappy v8
    XidianOJ 1036 分配宝藏
    XidianOJ 1090 爬树的V8
    XidianOJ 1088 AK后的V8
    XidianOJ 1062 Black King Bar
    XidianOJ 1091 看Dota视频的V8
    XidianOJ 1098 突击数论前的xry111
    XidianOJ 1019 自然数的秘密
    XidianOJ 1109 Too Naive
  • 原文地址:https://www.cnblogs.com/jeavenwong/p/8214752.html
Copyright © 2011-2022 走看看