算法重拾之路——合并排序

***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************

隶属于递归与分治

合并排序

问题描述:实现对n个元素的排序。

算法描述:不断将待排序的元素分成大小大致相同的两个子集合各自排序,最终将排序好的两个子集合合并。集合不断递归分下去,直至集合元素个数为1。

算法程序:

<span style="font-family:Comic Sans MS;"> int a[6]={1,6,4,3,5,2},b[6];

template< class Type >
void Merge( Type a[] , Type b[] , int left , int mid , int right )
{
    int i,j,k;
    i=left;
    j=mid+1;
    k=left;
    while( i<=mid && j<=right ) {
        if( a[i] < a[j] )   b[k++] = a[i++];
        else    b[k++] = a[j++];
    }

    if( i <= mid )  {
        for( ; i <= mid ; ++i )
            b[k++] = a[i];
    }
    if( j <= right )    {
        for( ; j <= right ; ++j )
            b[k++] = a[j];
    }
}

template< class Type >
void Copy( Type a[] , Type b[] , int left , int right )
{
    int i;
    for( i = left ; i <= right ; ++i )
        a[i] = b[i];
}

template< class Type >
void MergeSort( Type a[] , int left , int right )
{

    if( left < right )  {
        int i = (left+right)/2;
        MergeSort(a,left,i);
        MergeSort(a,i+1,right);
        Merge(a,b,left,i,right);
        Copy(a,b,left,right);
    }
}</span>

三个函数:

——MergeSort:对数组a的left到right位置进行排序

——Merge:将a[0:left] 与 a[mid+1:right] 合并到数组b中

——Copy:将数组b,复制到数组a中

算法分析:

Merge和Copy都可以在O(n)时间内算完,因此对n个元素进行排序,最坏情况下所需的计算时间T(n)满足:

T(n)
= O(1)
n≤1

2*T(n/2)+O(n)
n>1

解这个递归方程可得,T(n) = O(n*log(n) )

算法优化:

通过修改分治策略机制,将递归消除。算法MergeSort的递归过程只是将待排序集合一分为二,直至集合剩下一个元素位置,然后不断合并排好序的集合。

因此,我们可以直接相邻的元素两两配对,通过合并算法将它们排序,不断合并,最后达到排序的目的。

优化算法程序:

<span style="font-family:Comic Sans MS;">template< class Type >
void Merge( Type a[] , Type b[] , int left , int mid , int right )
{
    int i,j,k;
    i=left;
    j=mid+1;
    k=left;
    while( i<=mid && j<=right ) {
        if( a[i] < a[j] )   b[k++] = a[i++];
        else    b[k++] = a[j++];
    }

    if( i <= mid )  {
        for( ; i <= mid ; ++i )
            b[k++] = a[i];
    }
    if( j <= right )    {
        for( ; j <= right ; ++j )
            b[k++] = a[j];
    }
}

template<class Type>
void MergePass( Type x[] , Type y[] , int s , int n )
{
    int i = 0;
    while( i <= n-2*s )
    {
        Merge(x,y,i,i+s-1,i+2*s-1);
        i=i+2*s;
    }
    if( i+s < n )   Merge(x,y,i,i+s-1,n-1);
    else
        for(int j = i ; j <= n-1 ; ++j )
            y[j] = x[j];
}

template<class Type>
void MergeSort(Type a[],int n)
{
    Type *b = new Type[n];
    int s = 1;
    while( s < n )
    {
        MergePass(a,b,s,n);
        s+=s;
        MergePass(b,a,s,n);
        s+=s;
    }
}</span>

优化算法分析:

这个就是 自然合并排序算法,按照这个方式进行合并排序所需的合并次数最少。例如对于给出n个元素数组排好序的极端情况的排序,自然合并排序算法不需要执行合并步,而普通合并算法需要执行 log(n) 次合并。因此,此时自然合并排序算法需要O(n)的时间,而普通合并算法需要O(n*log(n))时间。

***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************

时间: 2024-10-12 22:24:39

算法重拾之路——合并排序的相关文章

算法重拾之路——快速排序

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 第一章:分治与递归 快速排序 算法描述: 同合并排序一样,就是对于一堆数据进行排序. 快排的原理就是,找一个标准,以这个标准为中心进行扩展.就像以前 做操 的时候,老师会说,以XXX为基准,成体操队形散开,这时,XXX左右的人分别就会向它看齐,并向外扩散.快排原

算法重拾之路——最大子段和

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 第二章:动态规划 >最大子段和< 算法描述: ?给定由n个整数(可能为负整数)组成的序列 a1,a2, ... , an ,求该序列形如  从ai 到 aj (i ≤ j)的子段和的最大值.当所有整数均为负整数时定义其最大值为0.根据这个定义,所求的最优值为:

算法重拾之路——最长公共子序列(LCS)

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 第二章:动态规划 最长公共子序列 算法描述: 一个给定序列的子序列是该序列中删去若干元素后得到的序列.确切的说,若给定序列 X={ x1,x2,...,xm },则另一序列 Z = { z1,z2, ... ,zk },是X的子序列是指存在一个严格递增下标序列

算法重拾之路——矩阵连乘问题

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 第二章:动态规划 矩阵连乘问题 算法描述: 给定n个矩阵{A1,A2,...,An},其中Ai 与 Ai+1 是可乘的,i=1,2, ... ,n-1.考察这n个矩阵的连乘积 A1A2, ... ,An. 由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同

算法重拾之路——strassen矩阵乘法

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 第一章:分治与递归 STRASSEN矩阵乘法 算法描述: 矩阵乘法是线性代数中最常见的问题之一,它在数值计算中有广泛的应用.设A 和 B 是两个n × n矩阵,它们的乘积AB同样是一个n×n矩阵.A和B的乘积矩阵C 中的元素cij定义为: 按照这个定义来看,计算

算法重拾之路——棋盘覆盖

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 隶属于递归与分治 棋盘覆盖问题 问题描述: 在一个2^k × 2^k个方格组成的棋盘中,若恰有一个方格与其他方格不同,则该方格为一特殊方格,且称该棋盘为一特殊棋盘.在棋盘覆盖问题中,用下图所示四种' L '型骨牌覆盖一个给定的特殊棋盘中除特殊方格之外的所有方格,

算法重拾之路——动态规划基础

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 闲谈: 快到期末了,身为计算机专业大三学生,各种大作业缠身,到了大三,不再局限于考试了,学校更重视的是实践能力,所以各种大作业啊,并行计算.软件工程.软件综合设计 等等,有些东西,要求做的,在前两年,没有学过,于是又去学习,基本要把时间榨干了,这本书看了很多,就

算法重拾之路——凸多边形最优三角剖分

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 第二章:动态规划 >凸多边形最优三角剖分< 算法描述: ? 多边形: 平面上一条分段线性闭曲线.即 一系列首尾相接的直线段所组成的. ? 通常用多边形顶点的逆时针序列表示 凸多边形,即 P = { v0,v1,...,vn-1 } 表示具有n条边,v0,v1,

算法重拾之路——大数乘法

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 隶属于递归与分治 描述:设X与Y都是n位十进制的整数,现在要计算它们的乘积XY. 朴素法:用小学时候学过的方法,模拟乘,这样计算步骤太多,效率很低,时间复杂度达到了O(n^2)的地步. 分治法:将n为十进制整数分为两段每段长为n/2位,如下所示: 所以,X= A