HF_Cherish

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

1、思想

采用分治法:将原问题分解成n个规模较小而结构与原问题相似的子问题;递归地解决这些子问题;合并其结果,即得解。

2、伪代码

分很简单,就是把n个元素分成n/2个元素的子序列。重点是合并,为了避免检查是否每个堆都是空的,我们在每一堆的底部放一个哨兵,它包含一个特殊的值∞。

合并的伪代码如下:

 1 //合并已排好序(升序)的字数组A[p..q]和A[q+1..r],为A[p..r]
 2 MERGE( A,p,q,r )
 3     n1 = q-p+1;
 4     n2 = r-q;
 5     //先把两个数组copy一份
 6     create arrays L[1..n1+1], R[1..n2+1];
 7     for( i=1; i<=n1; i++ )    
 8         do L[i] = A[i+p-1];
 9     for( i=1; i<=n2; i++ )
10         do R[i] = A[i+q];
11     L[n1+1] = ∞;
12     R[n2+1] = ∞;
13     //合并
14     i=1;
15     j=1;
16     for( k=p; k<=r; k++ )
17         do if (L[i]<R[j])
18             then A[k] = L[i];
19                 i++;
20             else A[k] = R[j];
21                 j++;

合并算法:

1 MERGE-SORT( A,p,r )
2     if p<r
3     then q = (p+r)/2;
4     MERGE-SORT( A,p,q );
5     MERGE-SORT( A,q+1,r );
6     MERGE( A,p,q,r );

3、程序

//merge a[m..n] and a[n+1..q]
void merge( int a[], int m, int n, int q ){
    int n1,n2,i,j;
    n1 = n-m+1;
    n2 = q-n;
    int b[n1+1],c[n2+1];
    for( i=0; i<n1; i++ )
        b[i] = a[m+i];
    for( i=0; i<n2; i++ )
        c[i] = a[n+i+1];
    b[n1] = INFINITE;
    c[n2] = INFINITE;

    i=j=0;
    for( int k=m; k<=q; k++ ){
        if( b[i]<c[j] ){
            a[k] = b[i];
            i++;
        }
        else{
            a[k] = c[j];
            j++;
        }
    }
}
void MergeSort( int a[], int n ){
    if( n<2 ) return;
    int m = n/2;
    MergeSort(a,m);
    MergeSort(a+m,n-m);
    merge(a, 0,m-1,n-1);
}

4、时间分析

采用递归树的方式,树深度为lgn,所以时间代价为O(nlgn)。

4、对比插入算法

因为有常熟因子的影响,插入算法中的常熟因子要远远小于合并算法的常数因子,所以,如果是小规模的算法排序,插入排序要优于合并排序。但若规模扩大时,运行时间增长量级影响更大,此时,合并排序远优于插入排序。

posted on 2013-12-16 10:52  HF_Cherish  阅读(323)  评论(0编辑  收藏  举报