算法---合并排序

来源:互联网 发布:手机软件编程 编辑:程序博客网 时间:2024/06/06 16:38

合并排序,将两个或多个有序表合并成一个有序表。将两个有序表合并成一个有序表称为二路合并。


方法一

a为待排序的数据,s为一个序列的起始序号,m为第1 个序列的结束序号,n为有序列的长度,r为一个数组

void mergestep(int a[],int r[],int s,int m,int n)
{
        int i,j,k;
        k=s;
        i=s;
        j=m+1;

        while(i <= m && j <= n)
        {
                if(a[i] <= a[j])
                        r[k++] = a[i++];
                else
                        r[k++] = a[j++];
        }
        while(i <= m)
                r[k++] = a[i++];
        while(j <= n)
                r[k++] = a[j++];
}


void mergepass(int a[],int r[],int n,int len)
{
        int s,e;
        s = 0;
        while(s+len < n)
        {
                e = s+2*len-1;
                if(e>=n)
                 e = n-1;
                mergestep(a,r,s,s+len-1,e);
                s = e+1;
        }
        if(s < n)
                for(;s<n;s++)
                r[s] = a[s];
}

void mergesort(int a[],int n)
{
        int *p;
        int len = 1;
        int f = 0;
        if(!(p=(int*)malloc(sizeof(int)*n)))
        {
                printf("malloc error\n");
                exit(0);
        }
        while(len < n)
        {
                if(f)
                 mergepass(p,a,n,len);
                else
                 mergepass(a,p,n,len);

                len *= 2;
                f = 1 - f;
        }
        if(f)
        for(f=0;f<n;f++)
         a[f] = p[f];
        free(p);
}



方法二

void merge1(int data[],int begin,int mid,int end)
{
    int len1,len2,i,j,k;
    int *left = NULL,*right = NULL;
    
    len1 = mid - begin +1;
    len2 = end - mid;
    //临时保存数据
    left = (int*)malloc(sizeof(int)*len1);
    right = (int*)malloc(sizeof(int)*len2);

    for(i=0;i<len1;i++)
        left[i] = data[begin+i];
    for(j=0;j<len2;j++)
        right[j] = data[mid+1+j];

    i=j=0;
    k=begin;
    while(i<len1 && j < len2)
    {
        if(left[i] <= right[j])
            data[k++] = left[i++];
        else
            data[k++] = right[j++];
    }
    //剩余数据处理
    for(;i<len1;i++)
        data[k++] = left[i];
    for(;j<len2;j++)
        data[k++] = right[j];    

    free(left);
    free(right);
}


void mergesort(int *data,int begin,int end)
{
    int mid;
    if(begin < end)
    {
        
        mid = (begin+ end) >> 1;
        //分开,从中间递归分开
        mergesort(data,begin,mid);
        mergesort(data,mid+1,end);
        //合并
        merge1(data,begin,mid,end);
    }
}

int main()
{
    int a[] = {100,12,3,18,5,4,9,11,44,22,333};
    int len = sizeof(a)/sizeof(a[0]);
    
    for(int i=0;i<len;i++)
        printf("%d\t",a[i]);
    printf("\n");

    mergesort(a,0,len-1);
    
    for(int i=0;i<len;i++)
        printf("%d\t",a[i]);
    printf("\n");

    return 0;    
}


0 0