| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1317 人关注过本帖, 3 人收藏
标题:求用归并法对数组排序的程序
只看楼主 加入收藏
青蝶
Rank: 2
等 级:论坛游民
帖 子:160
专家分:51
注 册:2018-2-4
结帖率:92%
收藏(3)
已结贴  问题点数:20 回复次数:9 
求用归并法对数组排序的程序
希望有大佬可以给一个用归并法对数组排序的程序,谢谢
搜索更多相关主题的帖子: 归并 数组 排序 
2018-05-18 13:32
自学的数学
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:46
帖 子:967
专家分:4146
注 册:2017-11-15
收藏
得分:10 
程序代码:
/***************************************************** 
File name:Quicksort 
Description: 对数组进行归并排序
Funcion List: 实现快速排序算法 
*****************************************************/  
  
#include <stdio.h>  
#include <stdlib.h>  
void Swap(int a[],int i,int j)
{
    int temp=a[i];
    a[i]=a[j];
    a[j]=temp;
}
void MergerSorting(int a[],int des[],int low,int mid,int high)
{
     int i=low;
     int j=mid+1;
     int k=low;
     while((i<=mid)&&(j<=high))
     {
           if(a[i]<a[j]) des[k++]=a[i++];
           else des[k++]=a[j++];
     }
     while(i<=mid) des[k++]=a[i++];
     while(j<=high) des[k++]=a[j++];
}

void MSorting(int a[],int des[],int low,int high,int max)
{
    if(low==high)
    {
         des[low]=a[low];
    }
    else
    {
      int mid=(low+high)/2;
      int* space=(int*)malloc(sizeof(int)*max);
      if(space!=NULL)
      {
          MSorting(a,space,low,mid,max);
          MSorting(a,space,mid+1,high,max);
          MergerSorting(space,des,low,mid,high);
          free(space);
      }
    }
}

void MerSorting(int a[],int len)
{
    MSorting(a,a,0,len-1,len);
}

void ShowSorting(int a[], int len)
{
    for(int i=0;i<len;i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
}

int main()
{
    int a[]={1,5,21,20,31,2,15,100};
    int len=sizeof(a)/sizeof(*a);
    //BubbleSorting(a,len);
    //SelectSorting(a,len);
    //InsertSorting(a,len);
    //ShellSorting(a,len);
    //QuickSorting(a,len);
    MerSorting(a,len);
    ShowSorting(a,len);
    return 0;
}
2018-05-18 14:20
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:10 
我也简单弄了个(感觉自己弄的不怎么样,看看就可以了)~

PS:加入了计时功能~

程序代码:
#include<stdio.h>
#include<stdarg.h>
#include<time.h>

void init_srand( long* );
void test1( size_t,... );
void test2( size_t,unsigned );
void test3( unsigned,unsigned,unsigned );
void check( int*,size_t );

void sort( int*,size_t );

static void _sort( int*,size_t,size_t );
static void _merge( int*,int*,int* );

void print( const int [],size_t size );

int main( void )
{    
    size_t i;

    time_t start;

    init_srand(NULL);

    start=time(NULL);

    test1(1,0);        //测试1个数
    test1(2,1,2);    //测试顺序两个数
    test1(2,2,1);    //测试逆序两个数
    test1(5,1,1,1,1,1);    //测试输入重复数
    test1(5,1,2,3,4,5);    //测试顺序5个数
    test1(5,5,4,3,2,1);    //测试逆序5个数
    test1(5,1,2,1,1,2);    //测试重复数
    test1(5,3,2,1,5,4);    //测试一般序列
    test1(5,-3,-2,-1,-5,-4);    //测试负数
   
    puts("ACROSS TEST1"); 

    for (i=1;i!=10001;++i)  //从1个数据到10000个数据每个数据段覆盖1次
        test2(i,1);

    puts("ACROSS TEST2");

    test3(1,1000000,10);  //随机产生1~1000000元素个数,测试10次

    puts("ACROSS TEST3");

    printf("The test of time is %g s\n",difftime(time(NULL),start));

    getchar();
        
    return 0;
}

#include<stdlib.h>

void init_srand( long* data )
{
    srand(( unsigned )time(data));
}

#include<string.h>
#include<assert.h>

void test1( size_t len,... )
{
    va_list ap;
    
    int* a=( int* )malloc(len*sizeof (*a));
    
    size_t i;
    
    assert(a);

    va_start(ap,len);
    for (i=0;i!=len;++i)
        a[i]=va_arg(ap,int);
            
    va_end(ap);
    
    sort(a,len);

    check(a,len);    //检查数据是否存在bug
    
    free(a);
}

void test2( size_t len,unsigned count )
{   
    int* buf=( int* )malloc(len*sizeof (*buf));
    
    assert(buf);

    do
    {
        size_t i;
        for (i=0;i!=len;++i)
            buf[i]=rand()%100;

        sort(buf,len);

        check(buf,len);    //检查数据是否存在bug
    }while (--count);
    
    free(buf);
}

void test3( unsigned low,unsigned height,unsigned count )
{
    size_t i;

    if (low>height)
    {
        fprintf(stderr,"TEST3 DATA RANGE ERROR\n");

        exit(EXIT_FAILURE);
    }

    for (i=0;i!=count;++i)
    {
        const size_t len=rand()%(height-low+1)+low;

        test2(len,1);
    }
}

void check( int* a,size_t len )
{
    size_t i;

    if (len<2)
        return ;

    for (i=0;i!=len-1;++i)
        assert(a[i]<=a[i+1]);
}

void sort( int* a,size_t size )
{
    if (size==0)
        return ;
        
    _sort(a,0,size);
}

static void _sort( int* a,size_t low,size_t height )
{    
    if (low>=height-1)
        return ;
        
   {
       const size_t mid=(low+height)/2;
       
       _sort(a,low,mid);
       _sort(a,mid,height);
      
       _merge(a+low,a+mid,a+height);
   }
}

#include<string.h>

static void _merge( int* p,int* q,int* p_height )
{
    const size_t len=p_height-p;

    const int* const p_mid=q;
    
    int* buf=( int* )malloc(len*sizeof (*buf));
    
    int* p_buf=buf;
    
    assert(buf);
    
    while (p!=p_mid&&q!=p_height)
        *(p_buf++)=*p<*q?*(p++):*(q++);
        
    if (p!=p_mid)
        memcpy(p_buf,p,(p_mid-p)*sizeof (*p));
    else
        memcpy(p_buf,q,(p_height-q)*sizeof (*q));

    memcpy(p_height-len,buf,len*sizeof (*buf));
    
    free(buf);
}

void print( const int a[],size_t size )
{
    size_t i;
    for (i=0;i!=size;++i)
        printf("%-4d",a[i]);
    puts("");
}


[此贴子已经被作者于2018-5-19 23:43编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-05-18 16:32
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-05-18 17:03
自学的数学
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:46
帖 子:967
专家分:4146
注 册:2017-11-15
收藏
得分:0 
归并排序法简介编辑
 归并排序法(Merge Sort,以下简称MS)是分治法思想运用的一个典范。其主要算法操作可以分为以下步骤:
Step 1:将n个元素分成两个含n/2元素的子序列
Step 2:用MS将两个子序列递归排序(最后可以将整个原序列分解成n个子序列)
Step 3:合并两个已排序好的序列
易知,MS的关键在于Merge过程。对于这一过程的理解,算法导论中给出了一个形象的模型。
即假设桌面上有两堆已排序好的的牌,且每一堆都正面朝下放置。然后我们分别从两堆牌中选取顶上的一张牌(选取之后,堆顶端又会露出新的顶牌),选取较小的一张,放入输出堆,另一张放回。
重复这一步骤,最后直到一堆牌为空。由于两堆牌都是已排序,所以可知,只要将剩下的那堆牌盖到输出堆即完成整个排序过程。
归并操作的工作原理如下:
第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾
将另一序列剩下的所有元素直接复制到合并序列尾。
2018-05-18 17:09
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 2楼 自学的数学


这个排序有亮点,就是充分用了原来辅助空间的数据来进行归并直到最后一次才放回原数组中,值得一看~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-05-18 17:16
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
弄了很久终于改好bug了,参考了2楼的方法,然后在空间上优化了一下[感觉具体不容易看懂,注释也很难描述清楚为啥要这样(具体就是用a数组和buf数组交替存储归并数据)其中逻辑bug改了很久,真的要理解或者可以试试画个树状图],看看就可以了~

2018-5-19更发现bug,当测试数据元素个数为129的时候就会出现bug

其实这说明了检测数据的必要性,以及检测数据的基本方法,测试其实只是一种方法,关键还是逻辑理解,解决方案在下楼放个简单代码,那个逻辑简单多了~



程序代码:
#include<stdio.h>
#include<stdarg.h>

void init_srand( long* );
void test1( size_t,... );
void test2( size_t,unsigned );
void check( int*,size_t );

void sort( int*,size_t );

static unsigned _sort( int*,int*,size_t,size_t );
static void _merge( int*,int*,int*,const int* );

void print( const int [],size_t size );


int main( void )
{    
    size_t i;

    test1(1,0);        //测试1个数
    test1(2,1,2);    //测试顺序两个数
    test1(2,2,1);    //测试逆序两个数
    test1(5,1,1,1,1,1);    //测试输入重复数
    test1(5,1,2,3,4,5);    //测试顺序5个数
    test1(5,5,4,3,2,1);    //测试逆序5个数
    test1(5,1,2,1,1,2);    //测试重复数
    test1(5,3,2,1,5,4);    //测试一般序列
    test1(5,-3,-2,-1,-5,-4);    //测试负数
    
    puts(""); 

    init_srand(NULL);

    for (i=1;i!=64;++i)  //从1个数据到64个数据每个数据段覆盖1次
        test2(i,1);
        
    return 0;
}

#include<stdlib.h>
#include<time.h>

void init_srand( long* data )
{
    srand(( unsigned )time(data));
}

#include<string.h>
#include<assert.h>

void test1( size_t len,... )
{
    va_list ap;
    
    int* buf=( int* )malloc(len*sizeof (*buf));
    
    size_t i;
    
    assert(buf);
    
    va_start(ap,len);
    for (i=0;i!=len;++i)
        buf[i]=va_arg(ap,int);
            
    va_end(ap);
    
    sort(buf,len);
    
    print(buf,len);

    check(buf,len);    //检查数据是否存在bug
    
    free(buf);
}

void test2( size_t len,unsigned count )
{   
    int* buf=( int* )malloc(len*sizeof (*buf));
    
    assert(buf);

    do
    {
        size_t i;
        for (i=0;i!=len;++i)
            buf[i]=rand()%100;

        sort(buf,len);
    
        print(buf,len);

        check(buf,len);    //检查数据是否存在bug
    }while (--count);

    puts("");
    
    free(buf);
}

void check( int* a,size_t len )
{
    size_t i;

    if (len<2)
        return ;

    for (i=0;i!=len-1;++i)
        assert(a[i]<=a[i+1]);
}

void sort( int* a,size_t size )
{        
    int* buf=NULL;

    if (size==0)
        return ;

    buf=( int* )malloc(size*sizeof (*buf));
    
    assert(buf);

    memset(buf,0,size*sizeof (*buf));
        
    if (_sort(a,buf,0,size)&1)
        memcpy(a,buf,size*sizeof (*buf));
    
    free(buf);
}

static unsigned _sort( int* a,int* buf,size_t low,size_t height )
{    
    const size_t mid=(low+height)/2;
      
    unsigned res=1;

    if (low>=height-1)
    {
        *(buf+low)=*(a+low);
             
        return 0;
    }
  
    if (height-mid>1) 
    {   
        _sort(a,buf,low,mid);      
        res=_sort(a,buf,mid,height)+1;
    }
    else 
    {
        _merge(buf+low,a+low,a+mid,a+height);
        _merge(a+low,buf+low,buf+mid,buf+height);

        return res;
    }

    if (((res&1)!=0)&&(res!=5))
        _merge(buf+low,a+low,a+mid,a+height);
    else if (((res&1)==0)&&(res!=2)&&(res!=4))
        _merge(a+low,buf+low,buf+mid,buf+height);
    else
    {
       _merge(a+low,buf+low,buf+mid,buf+height);
       _merge(buf+low,a+low,a+mid,a+height);
    }
          
    return res;
}

static void _merge( int* buf,int* p,int* q,const int* p_height )
{
    
    const size_t len=p_height-p;

    const int* const p_mid=q;
    
    int* p_buf=buf;
    
    while ((p!=p_mid)&&(q!=p_height))
        *(p_buf++)=*p<*q?*(p++):*(q++);
        
    if (p!=p_mid)
        memcpy(p_buf,p,(p_mid-p)*sizeof (*p));
    else
        memcpy(p_buf,q,(p_height-q)*sizeof (*q));
}

void print( const int a[],size_t size )
{
    size_t i;
    for (i=0;i!=size;++i)
        printf("%-4d",a[i]);
    puts("");
}


[此贴子已经被作者于2018-5-19 22:27编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-05-19 00:45
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
解决bug后新增了一种随机元素个数检测方法,先上代码,再简单说明~

程序代码:
#include<stdio.h>
#include<stdarg.h>
#include<time.h>

void init_srand( long* );
void test1( size_t,... );
void test2( size_t,unsigned );
void test3( unsigned,unsigned,unsigned );
void check( int*,size_t );

void sort( int*,size_t );

static void _sort( int*,int*,size_t,size_t,unsigned );
static void _merge( int*,const int*,const int*,const int* );

void print( const int [],size_t size );


int main( void )
{    
    size_t i;

    time_t start;

    init_srand(NULL);

    start=time(NULL);

    test1(1,0);        //测试1个数
    test1(2,1,2);    //测试顺序两个数
    test1(2,2,1);    //测试逆序两个数
    test1(5,1,1,1,1,1);    //测试输入重复数
    test1(5,1,2,3,4,5);    //测试顺序5个数
    test1(5,5,4,3,2,1);    //测试逆序5个数
    test1(5,1,2,1,1,2);    //测试重复数
    test1(5,3,2,1,5,4);    //测试一般序列
    test1(5,-3,-2,-1,-5,-4);    //测试负数
   
    puts("ACROSS TEST1"); 

    for (i=1;i!=10001;++i)  //从1个数据到10000个数据每个数据段覆盖1次
        test2(i,1);

    puts("ACROSS TEST2");

    test3(1,1000000,10);  //随机产生1~1000000元素个数,测试10次

    puts("ACROSS TEST3");

    printf("The test of time is %g s\n",difftime(time(NULL),start));

    getchar();
        
    return 0;
}

#include<stdlib.h>

void init_srand( long* data )
{
    srand(( unsigned )time(data));
}

#include<string.h>
#include<assert.h>

void test1( size_t len,... )
{
    va_list ap;
    
    int* a=( int* )malloc(len*sizeof (*a));
    
    size_t i;
    
    assert(a);

    va_start(ap,len);
    for (i=0;i!=len;++i)
        a[i]=va_arg(ap,int);
            
    va_end(ap);
    
    sort(a,len);

    check(a,len);    //检查数据是否存在bug
    
    free(a);
}

void test2( size_t len,unsigned count )
{   
    int* buf=( int* )malloc(len*sizeof (*buf));
    
    assert(buf);

    do
    {
        size_t i;
        for (i=0;i!=len;++i)
            buf[i]=rand()%100;

        sort(buf,len);

        check(buf,len);    //检查数据是否存在bug

    }while (--count);
    
    free(buf);
}

void test3( unsigned low,unsigned height,unsigned count )
{
    size_t i;

    if (low>height)
    {
        fprintf(stderr,"TEST3 DATA RANGE ERROR\n");

        exit(EXIT_FAILURE);
    }

    for (i=0;i!=count;++i)
    {
        const size_t len=rand()%(height-low+1)+low;

        test2(len,1);
    }
}

void check( int* a,size_t len )
{
    size_t i;

    if (len<2)
        return ;

    for (i=0;i!=len-1;++i)
        assert(a[i]<=a[i+1]);
}

void sort( int* a,size_t size )
{        
    int* buf=NULL;

    if (size==0)
        return ;

    buf=( int* )malloc(size*sizeof (*buf));
    
    assert(buf);

    memcpy(buf,a,size*sizeof (*buf));
   
    _sort(a,buf,0,size,1);
  
    free(buf);
}

static void _sort( int* a,int* buf,size_t low,size_t height,unsigned deep )
{    
    const size_t mid=(low+height)/2;

    if (low>=height-1)            
        return ;
  
    _sort(a,buf,low,mid,deep+1);      
    _sort(a,buf,mid,height,deep+1);

    if (deep&1)
        _merge(a+low,buf+low,buf+mid,buf+height);
    else
        _merge(buf+low,a+low,a+mid,a+height);
}

static void _merge( int* buf,const int* p,const int* q,const int* p_height )
{
    const int* const p_mid=q;
    
    int* p_buf=buf;
    
    while ((p!=p_mid)&&(q!=p_height))
        *(p_buf++)=*p<*q?*(p++):*(q++);
        
    if (p!=p_mid)
        memcpy(p_buf,p,(p_mid-p)*sizeof (*p));
    else
        memcpy(p_buf,q,(p_height-q)*sizeof (*q));
}

void print( const int a[],size_t size )
{
    size_t i;
    for (i=0;i!=size;++i)
        printf("%-4d",a[i]);
    puts("");
}


其实二分法本来就可以用一颗树来形容,根节点为第一层,当为层数为奇数的时候把数据从buf数组归并到a数组,否则就从a数组归并到buf数组,由于最底层可能就是奇数,所以可以在排序之前预先把a数组所有元素先复制到buf数组

PS:加入了计时功能~


[此贴子已经被作者于2018-5-20 02:59编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-05-19 22:16
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
3楼和8楼代码都加入了计时功能~
当然8楼执行效率要比3楼的要高是可以理解的(相对于3楼少了对归并后的数据的放回处理)~

正常来说8楼的运行时间应该是3楼的一半才是,但让我感到意外却是可以理解的是8楼的运行时间不到3楼的3分之1
那可以推出3楼频繁使用malloc和free会对执行效率有所影响,这其实也是一个优化的地方~

附上对比测试图:

这个是3楼代码~
图片附件: 游客没有浏览图片的权限,请 登录注册


这个是8楼代码~

图片附件: 游客没有浏览图片的权限,请 登录注册

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-05-19 23:54
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
然后把递归改成栈(测过快不了多少,甚至感觉还慢了那么一点点,看来相对递归来说用栈能提高运行效率还是要看具体情况的),加了比较函数封装,变成了和标准库函数qsort的形式~

但由于里面赋值改成memcpy这样调用函数要额外的开销,时间从9秒变成了18秒到21秒之间~
qsort稳定在25秒到27秒之间,比3楼的要快(如果按3楼的方法改写成10楼的形式,那相对而言还要快得多),比10楼的要慢,嗯,附上代码比对图片,算是这样了~

程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>
#include<time.h>


typedef void (*SORT_FUN)( void*,size_t,size_t,int (*)( const void*,const void* ) );

void sort_test( SORT_FUN );

int comp( const void*,const void* );    //比较函数

void init_srand( long* );
void test1( size_t,SORT_FUN,... );
void test2( size_t,unsigned,SORT_FUN );
void test3( unsigned,unsigned,unsigned,SORT_FUN );
void check( int*,size_t );

void merge_sort( void*,size_t,size_t,int (*)( const void*,const void* ) );

static void _merge( char*,const char*,const char*,const char*,size_t,\
                   int (*)( const void*,const void* ));

void print( const int [],size_t size );

int main( void )
{    
    puts("Test qsort:\n");
    sort_test(qsort);

    puts("\nTest merge_sort:\n");
    sort_test(merge_sort);

    getchar();
        
    return 0;
}

int comp( const void* p,const void* q )
{
    return *( int* )p-*( int* )q;
}

void sort_test( SORT_FUN sort_fun )
{
    size_t i;

    time_t start;

    init_srand(NULL);

    start=time(NULL);

    test1(1,sort_fun,0);        //测试1个数
    test1(2,sort_fun,1,2);    //测试顺序两个数
    test1(2,sort_fun,2,1);    //测试逆序两个数
    test1(5,sort_fun,1,1,1,1,1);    //测试输入重复数
    test1(5,sort_fun,1,2,3,4,5);    //测试顺序5个数
    test1(5,sort_fun,5,4,3,2,1);    //测试逆序5个数
    test1(5,sort_fun,1,2,1,1,2);    //测试重复数
    test1(5,sort_fun,3,2,1,5,4);    //测试一般序列
    test1(5,sort_fun,-3,-2,-1,-5,-4);    //测试负数
   
    puts("ACROSS TEST1"); 

    for (i=1;i!=10001;++i)  //从1个数据到10000个数据每个数据段覆盖1次
        test2(i,1,sort_fun);

    puts("ACROSS TEST2");

    test3(1,1000000,10,sort_fun);  //随机产生1~1000000元素个数,测试10次

    puts("ACROSS TEST3");

    printf("The test of time is %g s\n",difftime(time(NULL),start));
}

void init_srand( long* data )
{
    srand(( unsigned )time(data));
}

#include<string.h>
#include<assert.h>

void test1( size_t len,SORT_FUN sort_fun,... )
{
    va_list ap;
    
    int* a=( int* )malloc(len*sizeof (*a));
    
    size_t i;
    
    assert(a);

    va_start(ap,sort_fun);
    for (i=0;i!=len;++i)
        a[i]=va_arg(ap,int);
            
    va_end(ap);
    
    sort_fun(a,len,sizeof (int),comp);

    check(a,len);    //检查数据是否存在bug
    
    free(a);
}

void test2( size_t len,unsigned count,SORT_FUN sort_fun )
{   
    int* buf=( int* )malloc(len*sizeof (*buf));
    
    assert(buf);

    do
    {
        size_t i;
        for (i=0;i!=len;++i)
            buf[i]=rand()%100;

        sort_fun(buf,len,sizeof (int),comp);

        check(buf,len);    //检查数据是否存在bug

    }while (--count);
    
    free(buf);
}

void test3( unsigned low,unsigned height,unsigned count,SORT_FUN sort_fun )
{
    size_t i;

    if (low>height)
    {
        fprintf(stderr,"TEST3 DATA RANGE ERROR\n");

        exit(EXIT_FAILURE);
    }

    for (i=0;i!=count;++i)
    {
        const size_t len=rand()%(height-low+1)+low;

        test2(len,1,sort_fun);
    }
}

void check( int* a,size_t len )
{
    size_t i;

    if (len<2)
        return ;

    for (i=0;i!=len-1;++i)
        assert(a[i]<=a[i+1]);
}

typedef struct Stack
{

       size_t low;
    size_t height;

    unsigned deep;

       int flag; 
}Stack,*P_Stack;

#include<math.h>

void merge_sort( void* _a,size_t size,size_t n_size,int (*comp)( const void*,const void* ) )
{   
    char* buf=NULL;
    char* a=( char* )_a;

    P_Stack stack=NULL;
    P_Stack base=NULL;
    P_Stack top=NULL;

    if (size==0)
        return ;

    buf=( char* )malloc(size*n_size);
    
    assert(buf);

    memcpy(buf,a,size*n_size);

    base=stack=( P_Stack )malloc(( size_t )(log(size)+10)*sizeof (Stack));

    assert(stack);

    stack->flag=0; 

    top=base+1;   

    top->low=0;
    top->height=size;

    top->deep=1;
    
    top->flag=0;

#define __STACK_PUSH( top,_low,_height )    \
    do    \
    {    \
        ((top)+1)->low=(_low);    \
        ((top)+1)->height=(_height);    \
        ((top)+1)->deep=(top)->deep+1;    \
        ((top)+1)->flag=0;    \
        ++(top);    \
    }while (0);

#define __STACK_POP( top )    \
    do    \
    {    \
        --(top);    \
        ++(top)->flag;    \
    }while (0);

    while (top!=base)
    {
        const size_t low=top->low;
        const size_t mid=(top->low+top->height)/2;
        const size_t height=top->height;

        if (low==height-1)
        {
            __STACK_POP(top);
            continue;
        }

        if (top->flag==0)
        {
            __STACK_PUSH(top,low,mid);
            continue;
        }

        if (top->flag==1)
        {
            __STACK_PUSH(top,mid,height);
            continue;
        }

        if (top->deep&1)
            _merge(a+low*n_size,buf+low*n_size,buf+mid*n_size,buf+height*n_size,n_size,comp);
        else
            _merge(buf+low*n_size,a+low*n_size,a+mid*n_size,a+height*n_size,n_size,comp);

        __STACK_POP(top);
    }

    free(buf);

#undef __STACK_PUSH
#undef __STACK_POP
}

static void _merge( char* buf,const char* p,const char* q,const char* p_height,size_t n_size,\
                   int (*comp)( const void*,const void* ) )
{
    const char* const p_mid=q;
    
    char* p_buf=buf;

    while ((p!=p_mid)&&(q!=p_height))
        if (comp(p,q)>0)
        {
            memcpy(p_buf,q,n_size);

            p_buf+=n_size;
            q+=n_size;
        }
        else
        {
            memcpy(p_buf,p,n_size);

            p_buf+=n_size;
            p+=n_size;
        }

     if (p!=p_mid)
           memcpy(p_buf,p,p_mid-p);
        else
           memcpy(p_buf,q,p_height-q);
}

void print( const int a[],size_t size )
{
    size_t i;
    for (i=0;i!=size;++i)
        printf("%-4d",a[i]);
    puts("");
}


图片附件: 游客没有浏览图片的权限,请 登录注册


但意外地发现用手机测qsort是29秒,sort_merge是51秒感觉应该和编译器对底层基础的实现有关~

图片附件: 游客没有浏览图片的权限,请 登录注册


[此贴子已经被作者于2018-5-20 14:13编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-05-20 04:49
快速回复:求用归并法对数组排序的程序
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.030214 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved