新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     >>W3CHINA.ORG讨论区<<     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> We choose to study algorithmic problems,  not because they are easy,  but because they are hard.
    [返回] W3CHINA.ORG讨论区 - 语义网·描述逻辑·本体·RDF·OWL计算机理论与工程『 算法理论与分析 』 → 一个比较好的全排列算法(C语言) 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 11079 个阅读者浏览上一篇主题  刷新本主题   平板显示贴子 浏览下一篇主题
     * 贴子主题: 一个比较好的全排列算法(C语言) 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 算法理论与分析 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 一个比较好的全排列算法(C语言)

    全排列算法

    我有一个比较好的全排列算法,我验证了3、4、5的结果是正确的。

    程序中没有使用递归,只是几个循环,速度还令人满意。

    在C466A,Win2000的机器上,进行8个数字的全排列,结果不显示,重定向到一个文本文件中,耗时不到一秒钟

    。9个数字的全排列耗时6秒种。10个数字的全排列55秒种。(以上都不显示结果,均重定向到一个文本文件)

    11个数字的全排列(不显示结果,在原程序中不定义ISPRINT)耗时大约16秒钟。

    欢迎各位指点

    算法为:用两个数组,一个数组存放当前结果,第二个数组是每一个数是否已经使用的标志。比如对10个数进

    行全排列,第一个结果是:0 1 2 3 4 5 6 7 8 9。

    然后把每一个数的使用标志均置为1。

    然后开始主循环:

    先打印当前的结果。

    在前一个得到的结果中,从后往前找第一个由小到大排列的数。每找一次均置当前位上的数字的使用标志

    为0,然后找第一个比这个数大但是没有使用过的数。

    比如前一个结果是:4 1 9 7 8 2 5 0 6 3,那么从后往前第一个由小到大排列的数是0,第一个比0大但是没有

    使用过的数是3(因为比0大的数字里只有6和3)。最后由小到大依次打印剩余没有使用过的数字。所以下一个

    结果是4 1 9 7 8 2 5 3 0 6。

    源程序为(在BC++3.0下编译成功):

    #include<stdio.h>/*这两个库函数是习惯性的加上去的^_^。*/

    #include<stdlib.h>

    #define ISPRINT/*是否打印结果的标志*/

    #define MAX 200/*最大的数*/

    unsigned int *_NUM;/*用于存放一条结果的数组指针*/

    char *_NUMFLAG;/*用于存放是否已经使用的标志*/

    #define NUM(j) (*(_NUM+(j)))/*第j位的数字*/

    #define NUMFLAG(j) (*(_NUMFLAG+(j)))/*数字j是否已经使用的标志,0为没有使用,1为已经使用*/

    #define NUMUSE(j) (*(_NUMFLAG+(*(_NUM+(j)))))/*第j位上的数字是否已经使用的标志,0为没有使用,1为已

    经使用*/

    void main()

    {

    unsigned int number,j;

    int i;

    printf("\nInput number=");scanf("%u",&number);

    if((number>=MAX)||(number<=1)){puts("输入数据错误。");exit(-1);}

    /*初始化内存和第一个结果*/

    _NUM=(unsigned int*)malloc(sizeof(unsigned int)*number);

    if(!_NUM){puts("分配给_NUM出现内存不足");exit(-1);}

    _NUMFLAG=(char*)malloc(sizeof(char)*number);

    if(!_NUMFLAG){puts("分配给_NUMFLAG出现内存不足");exit(-1);}

    for(i=0;i<number;i++)NUM(i)=i,NUMFLAG(i)=1;/*初始化第一条结果和使用标志*/

    do{/*主循环*/

    #ifdef ISPRINT/*打印结果*/

    for(j=0;j<number;j++)printf("%d ",NUM(j));/*打印一条结果。*/

    puts("");/*并换行*/

    #endif

    NUMUSE(number-1)=0;//置最后一位数字的使用标志为0.

    /*在前一个结果中从后往前寻找第一个从小到大排列的数,并存放到变量j中*/

    for(i=number-2;i>=0;i--){

    NUMUSE(i)=0;

    if(NUM(i)<NUM(i+1))break;

    }

    if(i<0)break;/*从这里退出主循环.*/

    for(j=NUM(i)+1;j<number;j++){

    if(!NUMFLAG(j))break;

    }

    NUMFLAG(j)=1;

    NUM(i)=j;

    for(j=0,i++;i<number;j++)

    if(!NUMFLAG(j))NUM(i++)=j,NUMFLAG(j)=1;

    }while(1);

    /*释放内存*/

    free(_NUM);

    free(_NUMFLAG);

    }

    /*程序结束*/

    当然了这个程序的速度并不是最快的,程序中还有很大的优化余地,还可以减少一些循环,或者采用其他更好的算法。

    下载源程序http://263.csdn.net/FileBBS/files/2001_8/T_387_1.zip


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/9/19 8:13:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 算法理论与分析 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/5/10 7:11:23

    本主题贴数8,分页: [1]

     *树形目录 (最近20个回帖) 顶端 
    主题:  一个比较好的全排列算法(C语言)(2901字) - 卷积内核,2007年9月19日
        回复:  用什么工具查看程序运行时间?????(36字) - kinghere,2008年5月23日
        回复:  用回溯不行吗?(14字) - tq010or,2008年3月4日
            回复:  [quote][b]以下是引用[i]tq010or在2008-3-4 19:57:00[/i]的发..(119字) - netjian,2008年3月22日
        回复:  卷积兄,我用递归写了一遍该程序。也来和大家分享一下。排列结果不打印,只统计出最后有多少种排列方案..(1633字) - netjian,2008年3月3日
        回复:  太复杂了,应该看论文去才好,而且速度不快(40字) - bigc,2008年3月2日
        回复:  蛮不错的嘛(12字) - 水果柿子,2008年1月11日
        回复:  不错 看看(9字) - DMman,2007年9月19日

    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    5,218.750ms