二路归并算法非递归C实现

算法思想是Horowitz E.Sahni S. Fundamentals of Data Structures, 1976上的。二路归并的递归实现相对简单,但是非递归实现却有些绕脑。所以尝试写代码并做一些跟踪,才最终理解了这个算法。
 
#include <stdio.h>
#include <stdlib.h> 
// X[0] is guard
void Print(int *X, int n)
{
    printf("/n");
    for(int i=1; i<=n; i++){
        printf(" %d", X[i]);
    }
}
 
// merge X[l]..X[m], X[m+1]..x[n] to Z
void MERGE(int* X
           , int l/*first-sequence-start-postion, 1-based*/
           , int m/*first-sequence-length, 1-based*/
           , int n/*last-sequence-position, 1-based*/
           , int* Z)
{
    printf("/nMERGE(%08X, %d, %d, %d, %08X)", X, l, m, n, Z);
    int i, j, k, t;
    for(i=l, j=m+1, k=l; i<=m && j<=n; ){
        if(X[i]<=X[j]){Z[k++]=X[i]; ++i;}
        else{Z[k++]=X[j]; ++j;}
    }
 
    if(i>m){
        printf("/nMerge: i=%d > m=%d", i, m);
        for(t=j; t<=n; ++t)
            Z[k++] = X[t];            
    }else{
        printf("/nMerge: i=%d <= m=%d", i, m);
        for(t=i; t<=m; ++t)
            Z[k++] = X[t];
    }
}
 
// One pass for sort X[1+l*k]..x[1+l-1+l*k]
void MPASS(int* X, int* Y, int n, int l)
{
    printf("/nMPASS(%08X, %08X, %d, %d)", X, Y, n, l);
    int i=1;
    printf("/nMPASS(): i=%d", i);
    
    while(i<=n-2*l+1){
        MERGE(X, i, i+l-1, i+2*l-1, Y);
        i=i+2*l;
        printf("/nMPASS(): i=%d", i);
    }
 
    printf("/nMPASS(): i+l-1=%d, n=%d", i+l-1, n);
    // merge remaining file of length < 2l
    if(i+l-1<n){// "i+l-1"正好是下一个分区的中间值m
        // 如果m(=i+l-1)<n, 说明剩下的未归并分区中的数目多于“归并长度的一半”(即l/2)
        // 则还需要进行一次归并
        MERGE(X, i, i+l-1, n, Y);
    }else{
        // 否则,不需要再排序,因为这里只有不到本次归并长度一般的数目,显然已经在上一次归并循环中排好序了
        // 简单的拷贝即可,等待下一次2倍归并长度的排序
        for(int t=i; t<=n; ++t){
            Y[t] = X[t];
        }
    }
    Print(Y, n);
}
 
 
void MSORT(int* X, int n)
{
    int* Y = (int *)malloc(sizeof(int)*(n+1)/*Guard 1*/);
    int l = 1;
 
    printf("/nStart sorting!");
    Print(X, n);
    while(l<n){
        MPASS(X, Y, n, l);
        l = 2*l;
        MPASS(Y, X, n, l);
        l = 2*l;
    }
    free(Y);
    printf("/nFinished!");
}
 
int main(){
 
    int A[] = {0, 435, 6    };
    int B[] = {0, 7, 7435, 23, 66, 32, 75, 45, 886, 3456, 34234, 32, 45, 78, 8, 78, 34, 79, 567, 17, 34, 754, 345, 78, 9};
 
    MSORT(A, sizeof(A)/sizeof(A[0])-1);
    //MSORT(B, sizeof(B)/sizeof(B[0])-1);
 
    return 0;
}
阅读更多
个人分类: 计算机之道
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭