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

    >> We choose to study algorithmic problems,  not because they are easy,  but because they are hard.
    [返回] 计算机科学论坛计算机理论与工程『 算法理论与分析 』 → 一个比较好的全排列算法(C语言) 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 11149 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 一个比较好的全排列算法(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
     
     DMman 帅哥哟,离线,有人找我吗?魔羯座1984-1-11
      
      
      威望:1
      头衔:数据挖掘青年
      等级:研二(Pi-Calculus看得一头雾水)(版主)
      文章:803
      积分:5806
      门派:W3CHINA.ORG
      注册:2007/4/9

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给DMman发送一个短消息 把DMman加入好友 查看DMman的个人资料 搜索DMman在『 算法理论与分析 』的所有贴子 点击这里发送电邮给DMman 访问DMman的主页 引用回复这个贴子 回复这个贴子 查看DMman的博客2
    发贴心情 
    不错 看看

    ----------------------------------------------
    数据挖掘青年 http://blogger.org.cn/blog/blog.asp?name=DMman
    纪录片之家 (很多纪录片下载)http://www.jlpzj.com/?fromuid=137653

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/9/19 9:31:00
     
     水果柿子 美女呀,离线,快来找我吧!
      
      
      等级:大一(高数修炼中)
      文章:17
      积分:141
      门派:XML.ORG.CN
      注册:2008/1/11

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给水果柿子发送一个短消息 把水果柿子加入好友 查看水果柿子的个人资料 搜索水果柿子在『 算法理论与分析 』的所有贴子 引用回复这个贴子 回复这个贴子 查看水果柿子的博客3
    ===============================
    该用户发言已被管理员屏蔽
    ===============================
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/1/11 19:03:00
     
     bigc 帅哥哟,离线,有人找我吗?
      
      
      等级:大二(研究汇编)
      文章:34
      积分:238
      门派:XML.ORG.CN
      注册:2004/5/28

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给bigc发送一个短消息 把bigc加入好友 查看bigc的个人资料 搜索bigc在『 算法理论与分析 』的所有贴子 引用回复这个贴子 回复这个贴子 查看bigc的博客4
    发贴心情 
    太复杂了,应该看论文去才好,而且速度不快
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/3/2 23:46:00
     
     netjian 帅哥哟,离线,有人找我吗?白羊座1986-4-16
      
      
      头衔:智能入门者
      等级:大四(GRE考了1600分!)
      文章:198
      积分:1332
      门派:IEEE.ORG.CN
      注册:2007/5/5

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给netjian发送一个短消息 把netjian加入好友 查看netjian的个人资料 搜索netjian在『 算法理论与分析 』的所有贴子 点击这里发送电邮给netjian  引用回复这个贴子 回复这个贴子 查看netjian的博客5
    发贴心情 
    卷积兄,我用递归写了一遍该程序。也来和大家分享一下。
    排列结果不打印,只统计出最后有多少种排列方案,
    当排列个数小于9时,time = 0 s
    ……………等于9时,time = 2 s
    ……………等于10时,time = 20 s
    ……………等于
    代码清单如下:

    //该算法的计算过程是,利用递归,先从排列串中读出第一个字母存在临时串中第一个位置,然后将这个字母从原串中去掉,
    //再对原串进行如上子过程排列。

    #include "stdafx.h"
    #include <string.h>
    using namespace std;
    const int LENGTH = 9;//需要排列的字母个数
    char strCon[LENGTH + 1] = "ABCDEFGHI";//排列的串
    static char strTemp[LENGTH];//临时串
    static char str_get[LENGTH];//查找串
    static int count = 0 ;

    //查找出除去字母ch的str子串。例如,str[] = "ABC",ch = 'A',则返回"BC"。
    char * get_str(char str[] , char ch)//执行串
    {
     int len = strlen(str);
     int j=0;
     char *str_get = new char[len];//sorry,未能释放……
     for(int i = 0 ; i < len ;i++)
     {  
      if(str[i] != ch)
      {  
       str_get[j] = str[i];  
       j++;  
      }
     }
     str_get[len-1] = '\0';
     return str_get;
    }

    //打印函数
    void print()
    {
     for(int i = 0;i< LENGTH ;i++)
     {  
      cout<<strTemp[i];
     }
     cout<<endl;
    }

    //全排列函数
    void arrange(int place , char str_Do[])
    {
     if(place == LENGTH)
     {
      //print();  
      count++;
     }
     else
     {  
      for(int i = 0 ;i < strlen(str_Do);i++)
      {  
       strTemp[place] = str_Do[i];
       arrange(place+1 , get_str(str_Do , str_Do[i]));
      }
     }
    }

    int _tmain(int argc, _TCHAR* argv[])
    {
     arrange(0 , strCon);
     cout<<endl<<"共有"<<count<<"种解法!"<<endl;
     return 0;
    }


    [此贴子已经被作者于2008-3-3 17:53:42编辑过]

    ----------------------------------------------
    长江后浪,无坚不摧。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/3/3 17:03:00
     
     tq010or 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:1
      积分:55
      门派:XML.ORG.CN
      注册:2008/3/1

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给tq010or发送一个短消息 把tq010or加入好友 查看tq010or的个人资料 搜索tq010or在『 算法理论与分析 』的所有贴子 引用回复这个贴子 回复这个贴子 查看tq010or的博客6
    发贴心情 
    用回溯不行吗?
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/3/4 19:57:00
     
     netjian 帅哥哟,离线,有人找我吗?白羊座1986-4-16
      
      
      头衔:智能入门者
      等级:大四(GRE考了1600分!)
      文章:198
      积分:1332
      门派:IEEE.ORG.CN
      注册:2007/5/5

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给netjian发送一个短消息 把netjian加入好友 查看netjian的个人资料 搜索netjian在『 算法理论与分析 』的所有贴子 点击这里发送电邮给netjian  引用回复这个贴子 回复这个贴子 查看netjian的博客7
    发贴心情 
    以下是引用tq010or在2008-3-4 19:57:00的发言:
    用回溯不行吗?


    我在楼上用的不就是回溯么。

    ----------------------------------------------
    长江后浪,无坚不摧。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/3/22 10:35:00
     
     kinghere 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:4
      积分:68
      门派:XML.ORG.CN
      注册:2008/5/8

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给kinghere发送一个短消息 把kinghere加入好友 查看kinghere的个人资料 搜索kinghere在『 算法理论与分析 』的所有贴子 引用回复这个贴子 回复这个贴子 查看kinghere的博客8
    发贴心情 
    用什么工具查看程序运行时间?????
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/5/23 19:25:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 算法理论与分析 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/30 10:19:06

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

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    85.938ms