精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>C/C++>>算法集锦--------梦入玄机>>输出全排列算法讨论>>输出全排列的算法讨论

主题:输出全排列的算法讨论
发信人: ycs830()
整理人: girlrong(2000-03-08 18:49:15), 站内信件
    从1到N,输出全排列,共N!条。试试看!

--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.96.78.130]
发信人: girlrong (阿蓉), 信区: CLanguage
标  题: Re: 输出全排列,谁有更好的方法?
发信站: 网易 BBS (Tue Nov  9 10:55:34 1999), 转信

【 在 ycs830 (老山羊) 的大作中提到: 】
:     从1到N,输出全排列,共N!条。试试看!

    用N进制的方法吧。设一个N个单元的数组,对第一个单元做加一操作,满N进
一。每加一次一就判断一下各位数组单元有无重复,有则再转回去做加一操作,没
有则说明得到了一个排列方案。
    这种方法的要点就在于设计好的判断有无重复单元的算法,设计得好可以加快速度,
设计得不好速度就不敢恭维了。
    输出全排列在程序设计中很有用,大家都来提供点好方法吧。

--
※ 来源:.网易 BBS bbs.netease.com.[FROM: 202.103.244.15]
发信人: ycs830 (老山羊), 信区: CLanguage
标  题: Re: 输出全排列,谁有更好的方法?
发信站: 网易虚拟社区 (Tue Nov  9 11:03:29 1999), 站内信件

【 在 girlrong (阿蓉) 的大作中提到: 】
: 【 在 ycs830 (老山羊) 的大作中提到: 】
: :     从1到N,输出全排列,共N!条。试试看!
:     用N进制的方法吧。设一个N个单元的数组,对第一个单元做加一操作,满N进
: 一。每加一次一就判断一下各位数组单元有无重复,有则再转回去做加一操作,没
:    .......

    不敢恭维!

--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.96.78.130]
发信人: supermario (Mario), 信区: CLanguage
标  题: Re: 输出全排列,谁有更好的方法?
发信站: 网易虚拟社区 (Tue Nov  9 11:03:55 1999), 站内信件

【 在 girlrong (阿蓉) 的大作中提到: 】
: 【 在 ycs830 (老山羊) 的大作中提到: 】
: :     从1到N,输出全排列,共N!条。试试看!
:     用N进制的方法吧。设一个N个单元的数组,对第一个单元做加一操作,满N进
: 一。每加一次一就判断一下各位数组单元有无重复,有则再转回去做加一操作,没
:    .......
这种算法应该避免判断有无重复,要不然算法时间就会是直线上升,
我中学时基础没学好,想问一句什么是全排列?要不然可以没事的
时候想想。

--
点解啊,点解啊?
  -- 捶胸蹬足状

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.102.171.193]
发信人: ycs830 (老山羊), 信区: CLanguage
标  题: Re: 输出全排列,谁有更好的方法?
发信站: 网易虚拟社区 (Tue Nov  9 11:21:56 1999), 站内信件

【 在 supermario (Mario) 的大作中提到: 】

    N个人排队,列出所有排法。
    可以用递归,或循环,从1-N排起,从后边换起。

--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.96.78.130]
发信人: girlrong (阿蓉), 信区: CLanguage
标  题: Re: 输出全排列,谁有更好的方法?
发信站: 网易 BBS (Tue Nov  9 11:26:39 1999), 转信

【 在 ycs830 (老山羊) 的大作中提到: 】
: 【 在 girlrong (阿蓉) 的大作中提到: 】
: : 【 在 ycs830 (老山羊) 的大作中提到: 】
: :     用N进制的方法吧。设一个N个单元的数组,对第一个单元做加一操作,满N进
: : 一。每加一次一就判断一下各位数组单元有无重复,有则再转回去做加一操作,没
: :    .......

:     不敢恭维!

为什么?我用basic都可以实现,基本可用。要不你来个更好的,我这个方法确实
数目大了不行。

--
※ 来源:.网易 BBS bbs.netease.com.[FROM: 202.103.243.7]
发信人: girlrong (阿蓉), 信区: CLanguage
标  题: Re: 输出全排列,谁有更好的方法?
发信站: 网易 BBS (Tue Nov  9 11:41:37 1999), 转信

【 在 supermario (Mario) 的大作中提到: 】
: 【 在 girlrong (阿蓉) 的大作中提到: 】
: : 【 在 ycs830 (老山羊) 的大作中提到: 】
: :     用N进制的方法吧。设一个N个单元的数组,对第一个单元做加一操作,满N进
: : 一。每加一次一就判断一下各位数组单元有无重复,有则再转回去做加一操作,没
: :    .......
: 这种算法应该避免判断有无重复,要不然算法时间就会是直线上升,
: 我中学时基础没学好,想问一句什么是全排列?要不然可以没事的
: 时候想想。

    判断有无重复可以这样呀:再开一个数组,数组下标代表位置。而前一个数组
的单元值代表参与排列的元素的编号。第二个数组单元里如果为1说明该位置被占用
了,为0说明没被占用。以第一个数组的单元值为索引去看第二个数组单元是否为0
就可以知道位置是否被占用了,免了用循环判断有无重复。
    第二个数组也可以用c的位运算来代替。
     我这个办法是很久以前用的了,不知老山羊是不是不满足其速度?:)其实速度还
可以呀。

--
※ 修改:.girlrong 于 Nov  9 11:45:33 修改本文.[FROM: 202.103.243.7]
※ 来源:.网易 BBS bbs.netease.com.[FROM: 202.103.243.7]
发信人: supermario (Mario), 信区: CLanguage
标  题: Re: 输出全排列,谁有更好的方法?
发信站: 网易虚拟社区 (Tue Nov  9 12:02:00 1999), 站内信件

【 在 ycs830 (老山羊) 的大作中提到: 】
: 【 在 supermario (Mario) 的大作中提到: 】

:     N个人排队,列出所有排法。
:     可以用递归,或循环,从1-N排起,从后边换起。
:    .......
看来得用递归,循环的控制比较麻烦,用后退的方法比较方便。

--
点解啊,点解啊?
  -- 捶胸蹬足状

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.102.171.193]
发信人: terran (terran), 信区: CLanguage
标  题: Re: 输出全排列,谁有更好的方法?
发信站: 网易虚拟社区 (Tue Nov  9 12:33:28 1999), 站内信件

【 在 supermario (Mario) 的大作中提到: 】
: 【 在 ycs830 (老山羊) 的大作中提到: 】
: : 【 在 supermario (Mario) 的大作中提到: 】
: : 
: :     N个人排队,列出所有排法。
:    .......

用递归最方便!
但用循环并不是不行!只需要使用指针连接配合空间申请即可!



--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 210.75.56.43]
发信人: mrcloud (阿豪), 信区: CLanguage
标  题: Re: 输出全排列,谁有更好的方法?
发信站: 网易虚拟社区 (Tue Nov  9 13:27:52 1999), 站内信件

【 在 ycs830 (老山羊) 的大作中提到: 】
:     从1到N,输出全排列,共N!条。试试看!

用回溯啊?这是最好最正规的方法了。


--
阿豪 [email protected]
最好的BCB学习网站 C++Builder开发网络(http://a_hao.163.net)
C++Builder 论坛(http://cppbahao.abc.yesite.com)

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.101.20.116]
发信人: supermario (Mario), 信区: CLanguage
标  题: Re: 输出全排列,谁有更好的方法?
发信站: 网易虚拟社区 (Tue Nov  9 17:12:56 1999), 站内信件

【 在 girlrong (阿蓉) 的大作中提到: 】
: 【 在 supermario (Mario) 的大作中提到: 】
: : 这种算法应该避免判断有无重复,要不然算法时间就会是直线上升,
: : 我中学时基础没学好,想问一句什么是全排列?要不然可以没事的
: : 时候想想。
:    .......
今天上班糊涂了一天,只写了个开头,看看谁能?
#include <stdio.h>
#include <malloc.h>
main()
{
        int i,j,index;
        int *list,*out;
        printf("please input index number\n");
        scanf("%d",&index);

        if((list = calloc(index,sizeof(int))) == NULL){
                printf("calloc list fault!!!\n");
                exit(0);
        }

        if((out = calloc(index,sizeof(int))) == NULL){
                printf("calloc out fault!!!\n");
                exit(0);
        }

        for(i = 0;i < index;i++){
*(list + i) = i;
printf("%d",list[i]);
}

//add your code to ......
printf("program end!!!\n");

return(0);
}

--
点解啊,点解啊?
-- 捶胸蹬足状

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.102.171.193]
发信人: ycs830 (老山羊), 信区: CLanguage
标  题: 有关全排列的问题,再试试!
发信站: 网易虚拟社区 (Tue Nov  9 14:25:36 1999), 站内信件
    N>=17,所以考虑速度,因为N**N远远大于N!。
    有没有现成的方法,否则就用我今天晚上想出来的方法了。
    我想先从1到N自然排列,然后开始交换,第i个交换i次后,就该进位了,
i以后的重新排列。大概其就是这个思路。
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.96.79.14]
发信人: jackyrong (), 信区: CLanguage
标  题: Re: 有关全排列的问题,再试试!
发信站: 网易虚拟社区 (Tue Nov  9 16:26:20 1999), 站内信件
【 在 ycs830 (老山羊) 的大作中提到: 】
:     N>=17,所以考虑速度,因为N**N远远大于N!。

:     有没有现成的方法,否则就用我今天晚上想出来的方法了。

:    .......
用回溯最快,如:6!
#include <iostream.h>
const int n=6;
const int m=6;
int t;
int counter;
void out(const int a[m])
{
 int i1;
 for (i1=1;i1<=m;i1++)
cout<<a[i1]<<" ";
cout<<endl;
t=m;
counter=counter+1;
return;
}
int main()
{
counter=0;
const int m=3;
int i;
int a[m+1];
for (i=1;i<=m+1;i++)
a[i]=i;
out(a);
do {
if (a[t]==n-m+t) t=t-1;
else {
a[t]=a[t]+1;
if (t<m) for (i=t+1;i<=m;i++)
{a[i]=a[i-1]+1;}
out(a);
}
}
while (t!=0);
cout<<"The anwers are"<<counter<<endl;
return 0;
}
--
欢迎到最新 最全的学友成龙的网站:JACKYRONG.126.com
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: ]
发信人: girlrong (阿蓉), 信区: CLanguage
标  题: Re: 有关全排列的问题,再试试!
发信站: 网易虚拟社区 (Tue Nov  9 17:06:12 1999), 站内信件
【 在 ycs830 (老山羊) 的大作中提到: 】
:     N>=17,所以考虑速度,因为N**N远远大于N!。

:     有没有现成的方法,否则就用我今天晚上想出来的方法了。

:    .......
    天,大于17。哪怕只有17,全排列数也高达355687428096000,三百万亿种。
假设一秒钟输出三百万种(应该够快了吧?),全部输出也要一亿秒钟。老山羊啊,
不得了。
    这是我的方法。只要先把数组声明好,填上初始值,然后反复调用AddOne()
和Result(),全排列就出来了。函数AddOne()实在无法有效地结构化了,只好用
了两个goto。
    你的交换法应该比我的快。但我认为无论如何排列元素达17个以上是现在的
电脑所完成不了的。
#include <stdio.h>
#include <string.h>
typedef char MYTYPE;
void Result(MYTYPE * pPos,int n);
int AddOne(MYTYPE *pPos,MYTYPE *pPers,int n);
int main()
{
     int n;//参与排列的人数
     printf("请输入一个大于0的整数:");
     scanf("%d",&n);
     if(n<=0) return 1;
if(n>=10)
     {
         printf("最好别输这么大的数");
         return 1;
     }
     //下标代表位置编号,单元值代表占据该位置的人员编号
     MYTYPE *pPos=new MYTYPE[n*sizeof(MYTYPE)];
     //下标代表人员编号,单元值代表该人员是否参与了排列
     MYTYPE *pPers=new MYTYPE[n*sizeof(MYTYPE)];
     //用来统计排列数的变量
     int Total=0;
     //先造出第一种排列
     for(int i=0;i<n;i++)
{
pPos[i]=n-1-i;
pPers[i]=1;
}
Result(pPos,n);//第一种排列已经有了,输出。
Total++;
//下面输出剩下的各种排列
while(AddOne(pPos,pPers,n))
{
Result(pPos,n);
Total++;
}
printf("全排列数:%d\n\n\n",Total);
delete[] pPers;
delete[] pPos;
return 1;
}
////////////////////////////////////////////////
int AddOne(MYTYPE *pPos,MYTYPE *pPers,int n)
{
//返回值为1说明还可以有其他排列方案。返回值为0说明全排列已经全部处
理完毕。
//pPos[i]:编号为i的人员所占据的位置
//pPers[x]:编号为x的位置是否被人占据。0:空 1:被占据
int i=0;
aaa:
pPers[pPos[i]]=0;
bbb:
pPos[i]++;
if(pPos[i]>=n)
     {
        //需要进位
        pPos[i]=-1;//该位置的人员未定
        i++;
        if(i<n) goto aaa;
return 0;
}
if(pPers[pPos[i]])
{
//被占用了
goto bbb;
}
//既不需进位,该人员也未被占用
pPers[pPos[i]]=1;
i--;
//处理那些未定人员的位置
for(;i>=0;i--)
     {
         if(pPos[i]<0)
{
do
{
pPos[i]++;
}
while(pPers[pPos[i]]);
pPers[pPos[i]]=1;
}
}
return 1;
}
void Result(MYTYPE * pPos,int n)
{
for(int i=0;i<n;i++)
{
printf("%5d",pPos[i]+1);
}
printf("\n\n");
}
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.244.18]
发信人: zelor (张作乐), 信区: CLanguage
标  题: Re: 有关全排列的问题,再试试!
发信站: 网易虚拟社区 (Tue Nov  9 18:24:50 1999), 站内信件
   回溯的程序看得人头好大……哪位帮我掰一掰?
【 在 jackyrong () 的大作中提到: 】
: 【 在 ycs830 (老山羊) 的大作中提到: 】
: :     N>=17,所以考虑速度,因为N**N远远大于N!。
: : 
: :     有没有现成的方法,否则就用我今天晚上想出来的方法了。
:    .......
--
冬雷滚滚夏雨雪,
山无棱,天地合,
WINDOWS再没有BUG,
才敢与君绝!
                           ———作乐的爱情格言    
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.47.202]
发信人: supermario (发烧啦), 信区: CLanguage
标  题: Re: 有关全排列的问题,再试试!
发信站: 网易虚拟社区 (Tue Nov  9 20:50:35 1999), 站内信件
【 在 jackyrong () 的大作中提到: 】
: 【 在 ycs830 (老山羊) 的大作中提到: 】
: :     N>=17,所以考虑速度,因为N**N远远大于N!。
: : 
: :     有没有现成的方法,否则就用我今天晚上想出来的方法了。
:    .......
此算法有问题,不能得到正确结果,看在写了这么长的面子上
给20分。
--
点解啊,点解啊?
  -- 捶胸蹬足状
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.102.129.240]
发信人: zelor (张作乐), 信区: CLanguage
标  题: Re: 有关全排列的问题,再试试!
发信站: 网易虚拟社区 (Tue Nov  9 21:36:10 1999), 站内信件
    您给一个正确的行不行?这两天看程序看得头都大了。
    期中考试考不好怪你们。:P
【 在 supermario (发烧啦) 的大作中提到: 】
: 【 在 jackyrong () 的大作中提到: 】
: : 【 在 ycs830 (老山羊) 的大作中提到: 】
: :    .......
: 此算法有问题,不能得到正确结果,看在写了这么长的面子上
:    .......
--
冬雷滚滚夏雨雪,
山无棱,天地合,
WINDOWS再没有BUG,
才敢与君绝!
                           ———作乐的爱情格言    
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.47.202]

发信人: ycs830 (老山羊), 信区: CLanguage
标  题: 关于全排列问题,谢谢大家参与,请继续。
发信站: 网易虚拟社区 (Wed Nov 10 09:09:43 1999), 站内信件
    我是算术系毕业的,不知学计算机的仁兄们学没学过这个问题的标准
算法,按理说这是一个常用的算法,而且也锻炼能力,书上应该有。思路
我倒是有,实现也不困难,但是想速度快点。
    只要遍历就行,不必考虑顺序,也不必考虑输出后文件太大,因为我
只是想在其中筛选。而且不必非得到17,咱只是讨论算法。
    程序请用标准c写,N的值由用户输入,用动态数组,我可以在小型机
上玩。
    不写程序写出思路也行,大家可以共同探讨,找出更好的方法。仁者
见仁,智者见智。既然在c区讨论,找出好方法就行。
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.96.79.14]
发信人: mrcloud (阿豪), 信区: CLanguage
标  题: Re: 关于全排列问题,谢谢大家参与,请继续。
发信站: 网易虚拟社区 (Wed Nov 10 09:37:07 1999), 站内信件
【 在 ycs830 (老山羊) 的大作中提到: 】
:     我是算术系毕业的,不知学计算机的仁兄们学没学过这个问题的标准
: 算法,按理说这是一个常用的算法,而且也锻炼能力,书上应该有。思路
: 我倒是有,实现也不困难,但是想速度快点。
:     只要遍历就行,不必考虑顺序,也不必考虑输出后文件太大,因为我
:    .......
还有一个办法,不过链表插入可能导致速度太慢。
要得到n的全排列,只要在n-1全排列的基础上,一个隔一个插入n即可,
所以可以用递归极方便地实现,但我找不到好的插入算法。
--
阿豪 [email protected]
最好的BCB学习网站 C++Builder开发网络(http://iamahao.yeah.net)
C++Builder 论坛(http://cppbahao.abc.yesite.com)
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.101.16.129]
发信人: ycs830 (老山羊), 信区: CLanguage
标  题: Re: 关于全排列问题,谢谢大家参与,请继续。
发信站: 网易虚拟社区 (Wed Nov 10 09:46:13 1999), 站内信件
【 在 mrcloud (阿豪) 的大作中提到: 】
    内存得大得惊人,否则无法记忆N-1次的全排列。用磁盘倒?慢!
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.96.79.14]
发信人: girlrong (阿蓉), 信区: CLanguage
标  题: Re: 关于全排列问题,谢谢大家参与,请继续。
发信站: 网易虚拟社区 (Wed Nov 10 10:16:11 1999), 站内信件
【 在 ycs830 (老山羊) 的大作中提到: 】
: 【 在 mrcloud (阿豪) 的大作中提到: 】
:     内存得大得惊人,否则无法记忆N-1次的全排列。用磁盘倒?慢!
    n个元素全排列,每得到(n-1)个元素的全排列,就把第n个元素和那n-1个元
素依次交换,每交换一次就是一个n个元素的全排列。交换可以象冒泡法排序那样
相邻两个元素进行交换,这样就免了阿豪的方法中的链表的插入操作。例如:
    4   3   2   1
    假设 3   2   1 已经是n-1个元素的全排列,那么第n个元素4可以这样交换

    3   4   2   1
    3   2   4   1
    3   2   1   4
    每交换一次就是个新的n个元素的全排列。等我想想看如何实现。
    也没必要把每次的全排列都记在内存里,用过就可以丢了嘛。
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.243.166]
发信人: mrcloud (阿豪), 信区: CLanguage
标  题: Re: 关于全排列问题,谢谢大家参与,请继续。
发信站: 网易虚拟社区 (Wed Nov 10 11:06:12 1999), 站内信件
【 在 ycs830 (老山羊) 的大作中提到: 】
: 【 在 mrcloud (阿豪) 的大作中提到: 】
:     内存得大得惊人,否则无法记忆N-1次的全排列。用磁盘倒?慢!
不需要啊?
我是说用递归,在最下一层输出。无须记忆n-1的全排列。
--
阿豪 [email protected]
最好的BCB学习网站 C++Builder开发网络(http://iamahao.yeah.net)
C++Builder 论坛(http://cppbahao.abc.yesite.com)
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.101.16.129]
发信人: mrcloud (阿豪), 信区: CLanguage
标  题: Re: 关于全排列问题,谢谢大家参与,请继续。
发信站: 网易虚拟社区 (Wed Nov 10 11:09:26 1999), 站内信件
【 在 girlrong (阿蓉) 的大作中提到: 】
: 【 在 ycs830 (老山羊) 的大作中提到: 】
: : 【 在 mrcloud (阿豪) 的大作中提到: 】
: :     内存得大得惊人,否则无法记忆N-1次的全排列。用磁盘倒?慢!

:    .......
不错!
--
阿豪 [email protected]
最好的BCB学习网站 C++Builder开发网络(http://iamahao.yeah.net)
C++Builder 论坛(http://cppbahao.abc.yesite.com)
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.101.16.129]
发信人: ycs830 (老山羊), 信区: CLanguage
标  题: Re: 关于全排列问题,谢谢大家参与,请继续。
发信站: 网易虚拟社区 (Wed Nov 10 11:55:53 1999), 站内信件
【 在 girlrong (阿蓉) 的大作中提到: 】
    嘿嘿,1到3的排列方法共有3!种,以此类推。
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.96.78.129]
发信人: terran (terran), 信区: CLanguage
标  题: Re: 关于全排列问题,谢谢大家参与,请继续。
发信站: 网易虚拟社区 (Wed Nov 10 14:51:15 1999), 站内信件
【 在 girlrong (阿蓉) 的大作中提到: 】
: 【 在 ycs830 (老山羊) 的大作中提到: 】
: : 【 在 mrcloud (阿豪) 的大作中提到: 】
: :     内存得大得惊人,否则无法记忆N-1次的全排列。用磁盘倒?慢!

:    .......
girlrong 你如果不用递归,不用动态指针的话,N的数值回受到限制的.不好!
解决方法可以是:
   在一个function x中用for,并把for中的极大限制指传递归给function x
,然后在配合指针空间的申请!就ok了!
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 210.75.56.43]
发信人: girlrong (阿蓉), 信区: CLanguage
标  题: Re: 关于全排列问题,谢谢大家参与,请继续。
发信站: 网易虚拟社区 (Wed Nov 10 22:15:23 1999), 站内信件
【 在 terran (terran) 的大作中提到: 】
: 【 在 girlrong (阿蓉) 的大作中提到: 】
: : 【 在 ycs830 (老山羊) 的大作中提到: 】
: : 
: :    .......
:    .......
我前面给了个例子,没有用递归。算到8都还可以。今天想了一下递归,发现用递
归需控制的东西还更多。你有什么好主意没有?
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.243.1]

发信人: ycs830 (老山羊), 信区: CLanguage
标  题: 关于全排列,这样行不行
发信站: 网易虚拟社区 (Wed Nov 10 17:24:19 1999), 站内信件
    我大概其试了一下,这样行不行?明天再改进。循环次数应该正好。
    语句写得不好,调了半天。
# include <stdio.h>
# define N 7
main()
{
int i,j,k,m,n,l[N],a[N];
/*  赋初值 */
 
for(i=0;i<N;i++)
{
a[i]=0;l[i]=i; /* a[i]-1是第i个元素交换的次数 */
}
k=1;m=2;put(l);
while(1)
{
n=l[1];l[1]=l[0];l[0]=n;put(l); /* 头两个先换一下 */
/* 判断该换哪个了 */
while(a[m-2] == m)
m++;
if(m==N) break;
/* 下面是整理过程,可能还有办法 */
j=0;n=m/2;
for(i=0,j=m-1;i<n;i++,j--)
{
k=l[i];
l[i]=l[j];
l[j]=k;
} /* 以上是从小到大重排,下面处理好了可能不必做,因为可以无序
*/
a[m-2]++;
/* 下面该把第j个和第m个交换 */
j=m-a[m-2];
n=l[j];l[j]=l[m];l[m]=n;
put(l);
/* m以前的重排 */
for(i=0;i<m-2;i++)
a[i]=0;
m=2;
}
}
put(int *l)
{
int i;
for(i=0;i<N;i++)
printf("%d",l[i]);
putchar('\n');
}
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.96.78.129]
发信人: jackyrong (), 信区: CLanguage
标  题: Re: 关于全排列,这样行不行
发信站: 网易虚拟社区 (Wed Nov 10 18:28:09 1999), 站内信件
【 在 ycs830 (老山羊) 的大作中提到: 】
:     我大概其试了一下,这样行不行?明天再改进。循环次数应该正好。
:     语句写得不好,调了半天。
: # include <stdio.h>
: # define N 7
:    .......
思想:用A:ARRAY[1。。N] OF INTEGER 放元素
  初始化:
for i:=1 to n do a[i]:=i;
输出 A1,A2,。。。AN;
FOR I:=2 TO N ! DO
BEGIN
 求出A1,A2,。。。。。AN的下一个排列;
  输出A1,A2,A3,。。。AN;
以N=4为例,
在1234每个数字上加上箭头,〈- 〈-〈-〈-
                         1   2  3  4,当箭头所指一侧的数比该数小时,
称为该数的活动壮态,即1234中,2,3,4该处于活动壮态
1)   输出A1,A2,。。。AN作为一种生成的排列,若拍列中已没有处于活动
壮态的元素,生成过程结束,否则转第二步
2) 求处于活动壮态的最大值,设为M,并将其和箭头一侧的元素交换(包括
箭头);
3)  比M大的所有元素的箭头改向,转第1)。
对1234,则
  1234      〈-〈-〈-〈-
             1  2  3  4
  1243     〈-〈-〈-〈-
           1243
   1423    〈-〈-〈-〈-
            1423
   4123    〈-〈-〈-〈-
            4 1 2 3
   4132    -〉〈-〈-〈-
           4   1   3  2
   1432    〈- -〉〈-〈-
            1  4   3  2
   1342    〈-〈-  -〉  〈-
            1   3   4    2
。。。。。。
   2134        〈-〈-  -〉  -〉
                2  1   3    4
     
--
欢迎到最新 最全的学友成龙的网站:JACKYRONG.126.com
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: ]
发信人: zelor (张作乐), 信区: CLanguage
标  题: Re: 关于全排列,这样行不行
发信站: 网易虚拟社区 (Wed Nov 10 19:46:49 1999), 站内信件
列一个数组arr[n];
用一个指向该叔祖的指针p;
for (i=1;i<=n;i++)
对p进行模i的加法,不断通过p打印值……;
这样行不行得通?好象还有很多细节没有注意到?
临时所写,瞎灌一篇。
【 在 jackyrong () 的大作中提到: 】
: 【 在 ycs830 (老山羊) 的大作中提到: 】
: :     我大概其试了一下,这样行不行?明天再改进。循环次数应该正好。
: :     语句写得不好,调了半天。
: : # include <stdio.h>
:    .......
--
你说我是新手,那么你错了。
你说我是高手,那么我错了。
                     ——篡改自某部反映青少年题材的电视剧
                        
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.45.170]
发信人: supermario (发烧啦), 信区: CLanguage
标  题: Re: 关于全排列,这样行不行
发信站: 网易虚拟社区 (Wed Nov 10 21:21:20 1999), 站内信件
【 在 ycs830 (老山羊) 的大作中提到: 】
:     我大概其试了一下,这样行不行?明天再改进。循环次数应该正好。
:     语句写得不好,调了半天。
: # include <stdio.h>
: # define N 7
:    .......
速度不错,当N = 8时在PII400上只要两分钟,比阿蓉的快一些,
但是两台机器不太一样,回去再比较一下。
--
点解啊,点解啊?
  -- 捶胸蹬足状
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.102.129.253]
发信人: girlrong (阿蓉), 信区: CLanguage
标  题: Re: 关于全排列,这样行不行
发信站: 网易虚拟社区 (Wed Nov 10 22:49:48 1999), 站内信件
【 在 ycs830 (老山羊) 的大作中提到: 】
:     我大概其试了一下,这样行不行?明天再改进。循环次数应该正好。
:     语句写得不好,调了半天。
: # include <stdio.h>
: # define N 7
:    .......
    试了一下,用递归要控制太多东西。我这里有个递归的框架,正好处理次数
也是n!。但不知道交换和输出的代码该加在哪里,高手们有兴趣试试看。
    老山羊真出了个难题。
#include <stdio.h>
#include <string.h>
typedef char MYTYPE;
int total=0;
int Permute(MYTYPE *pPos,int i,int n);
int main()
{
     int n;//参与排列的人数
     printf("请输入一个大于0的整数:");
     scanf("%d",&n);
     if(n<=0) return 1;
MYTYPE *pPos=new MYTYPE[n];
//用来统计排列数的变量
int Total=0;
Permute(pPos,1,n);
printf("\n\n全排列数:%d\n\n",total);
delete[] pPos;
return 1;
}
int Permute(MYTYPE *pPos,int i,int n)
{
int k,m=n-1;
for(k=i;k>=0;k--)
     {
         if(i==m)
         {
              //也许交换和输出的代码应该写在这里
              total++;
         }
         if(i<m) Permute(pPos,i+1,n);
}
return 1;
}
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.243.1]
发信人: mrcloud (阿豪), 信区: CLanguage
标  题: Re: 关于全排列,这样行不行
发信站: 网易虚拟社区 (Thu Nov 11 00:05:43 1999), 站内信件
【 在 ycs830 (老山羊) 的大作中提到: 】
:     我大概其试了一下,这样行不行?明天再改进。循环次数应该正好。
:     语句写得不好,调了半天。
: # include <stdio.h>
: # define N 7
:    .......
还是用递归吧,在我的k6-233上,N=8只用不到10秒。
优化一下可以更快。
const int MAX=8;
int number[MAX];
void InsertNum(int n);
void OutPut();
unsigned int count=0;
//--------------------------------------------------------------------
-------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  InsertNum(1);
  Edit1->Text=IntToStr(count);
}
//--------------------------------------------------------------------
-------
void InsertNum(int n)
{
  bool End=false;
  if(n==MAX)
    End=true;
  number[n-1]=n;
  int temp;
  for(int i=0;i<n;i++)
{
if(i)
{
temp=number[n-i];
number[n-i]=number[n-i-1];
number[n-i-1]=temp;
}
if(End)
OutPut();
else
{
InsertNum(n+1);
for(int j=0;j<n;j++)
number[j]=number[j+1];
}
}
}
void OutPut()
{
AnsiString Result="";
for(int i=0;i<MAX;i++)
Result+=number[i];
Form1->RichEdit1->Lines->Strings[count++]=Result;
}
--
阿豪 [email protected]
最好的BCB学习网站 C++Builder开发网络(http://iamahao.yeah.net)
C++Builder 论坛(http://cppbahao.abc.yesite.com)
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.96.243.143]
发信人: mrcloud (阿豪), 信区: CLanguage
标  题: Re: 关于全排列,这样行不行
发信站: 网易虚拟社区 (Thu Nov 11 00:17:09 1999), 站内信件
【 在 mrcloud (阿豪) 的大作中提到: 】
Sorry,差点忘记说了,谢谢girlrong给我灵感,用交换代替插入操作。
--
阿豪 [email protected]
最好的BCB学习网站 C++Builder开发网络(http://iamahao.yeah.net)
C++Builder 论坛(http://cppbahao.abc.yesite.com)
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.96.243.143]

发信人: ycs830 (老山羊), 信区: CLanguage
标  题: 有关全排列,我改动一下,变成这样
发信站: 网易虚拟社区 (Thu Nov 11 10:01:02 1999), 站内信件
    这两天我抛出一块砖头,引来这么多美玉,真是受惠非浅。我把程
序改动了一下,变成这样啦,智力和精力所限,我也改不动了。各位的
程序我好好读一读,开拓一下自己的思路。
    下面我们是否讨论一下组合了?但组合好像较简单,从M个球里取N
个,列出所有组合,不用排列了,所以从大到小即可。可重复取样的也
很简单,比如从扑克牌中取出4张算24,哪天我试试看。
# include <stdio.h>
# include <alloc.h>
int N;
main()
{
int i,j,k,m,n,*l,*a,m2;
scanf("%d",&N);
if(N<3)
{
puts("N太小!");
exit(1);
}
/* 开数组 */
l=malloc(N*sizeof(int));
a=malloc(N*sizeof(int));
/* 赋初值 */
for(i=0;i<N;i++)
{
a[i]=0;l[i]=i+1; /* a[i]-1是第i个元素交换的次数 */
}
m=2;put(l);
do
{
n=l[1];l[1]=l[0];l[0]=n;put(l); /* 头两个先换一下 */
/* 判断该换哪个了 */
while(a[m-2] == m)
m++;
if(m==N) break;
/* 下面是整理过程,可能还有办法 */
n=m>>1;
  for(i=0,j=m-1;i<n;i++,j--)
{
k=l[i];
l[i]=l[j];
l[j]=k;
} /* 以上是从小到大重排,下面处理好了可能不必做,因为可以无序
*/
m2=m-2;
a[m2]++;
/* 下面该把第j个和第m个交换 */
j=m-a[m2];
n=l[j];l[j]=l[m];l[m]=n;
put(l);
/* m以前的重排 */
for(i=0;i<m2;i++)
a[i]=0;
m=2;
} while(1);
}
put(int *l)
{
int i;
for(i=0;i<N;i++)
printf(" %2d",l[i]);
putchar('\n');
}
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.96.78.129]

发信人: grsm (grsm), 信区: CLanguage
标  题: 我也写一个全排列的程序
发信站: 网易虚拟社区 (Thu Nov 11 16:55:14 1999), 站内信件
看了老山羊的题目,觉得很有意思,也写了一段程序。
#include <stdio.h>
#define n  5
int a[n],b[n];
void swap(int m)
{
  int b1=b[m];
  int b0=b1;
  while(a[b0]>=m){
    b0--;
    if(b0<0)b0=n-1;
}
int temp=a[b0];
a[b0]=a[b1];
a[b1]=temp;
int a0=a[b0];
int a1=a[b1];
temp=b[a0];
b[a0]=b[a1];
b[a1]=temp;
}
void output()
{
for(int j=0;j<n;j++){
printf("%d ",a[j]);
}
printf("\n");
}
void permute(int m)
{
m--;
for(int i=m;i>=0;i--){
    permute(m);
    if(i>0){
      swap(m);
      output();
    }
  }
}
void main()
{
  for(int i=0;i<n;i++){
a[i]=b[i]=i;
}
output();
permute(n);
}
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.102.240.99]

发信人: girlrong (阿蓉), 信区: CLanguage
标  题: 全排列问题答案大比武
发信站: 网易虚拟社区 (Thu Nov 11 22:05:02 1999), 站内信件
    不少人都做了老山羊的全排列问题,共有五人给出了六个程序。看了一下,
jackyrong的程序有问题,没有输出全排列,而是输出了顺次加一的自然数。ter
ran的程序也得不出结果,并且还有些语法错误。你们两位的算法可能没问题,只
是没有经过调式。阿豪的程序最怪,初次编译,竟有错误无数。再一看,原来是
用bcb写的。只好先化为vc6.0下的console程序(向阿豪保证,绝对没有伤及算法
部分)。还有个奇怪的地方。老山羊的put函数居然没有原型,难道在老山羊的编
译器上函数可以没有原型?当然,这也不是问题,在我这里加上就好了。
    先看准确性。以4个元素全排列,将结果重定向到文件里查看,大家的结果都
很完整。
    再看速度。 在我的P200MMX,64M内存机器上,删除所有程序中的输出语句,
然后算10个元素的全排列,四个程序所花时间如下:
            老山羊的第一个程序:5秒
            老山羊的第二个程序:5秒
            阿豪的程序:6秒
            grsm的程序:10秒
            斑竹我的程序:16秒
    呜呼,为什么我的程序这么慢?看来得把大家的程序好好学学。
    全排列问题很有用。在解决某些问题时需要穷举各种可能的情况,这时全排
列问题就可派上用场了。正好精华区里开了个算法集锦的栏目,这是个很好的例
子,稍后把各个程序都放进去,大家可以参考。
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.244.34]

发信人: supermario (夜游九州), 信区: CLanguage
标  题: 算法主要考虑的因素
发信站: 网易虚拟社区 (Fri Nov 12 01:09:35 1999), 站内信件
看了大家的全排列算法,想指出一点,算法的主要目的是减少
程序执行时间,首先要考虑的是减少循环次数,象用筛法从
n*n个递增数组里去掉有相同值的方法是不可取的,然后就是
控制循环的嵌套层数,尽可能的将多重循环变为更少层数的循
环,然后就是函数调用,要知道当一个算法执行的次数越多,
由于函数调用带来的附加机器指令就不可忽视,阿蓉的程序就
有这个问题,由于采用了外部函数的调用,每次入栈出栈就增
加了不少的附加指令,所以在写这样的程序时要尽量减少函数
调用,最好所有的循环操作在一个函数里完成。这也是程序结
构化与执行效率的矛盾,我以前为了赶工写的很多程序,结果
在后期整理时为了增强程序的可读性,将很多为了不想调用来
调用去而全部写在一个主函数的功能代码做成函数形式移出
main(),结果发现程序的执行效率大大降低。这是很好笑的
一件事。
另外就是算法对内存的要求,这个我倒是一般不注意,我用的
机器上一般都有2G以上的内存,但是在PC平台上,这也是应该
注意的。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  人生五十年,去事恍如梦幻;下天之内,岂有长生不死者
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  人生得意需尽欢,莫使金樽空对月
---------------------------------------------------
     我的心早已经一片黑暗,再没有什么是可以点燃。
---------------------------------------------------
--
点解啊,点解啊?
  -- 捶胸蹬足状
※ 修改:.supermario 于 Nov 12 03:18:39 修改本文.[FROM: 202.102.171.158]
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: bbs.szptt.net.c]

发信人: mrcloud (阿豪), 信区: CLanguage
标  题: Re: 全排列问题答案大比武
发信站: 网易虚拟社区 (Fri Nov 12 11:58:50 1999), 站内信件
【 在 supermario (发烧啦) 的大作中提到: 】
: 【 在 mrcloud (阿豪) 的大作中提到: 】
: : 【 在 supermario (发烧啦) 的大作中提到: 】
: :    .......
: 阿豪啊,你的程序好像有问题,我运行了4分多钟还没结果,
:    .......
我又编译了一次去掉了一句话:“//--------”
把return的返回值加上了。
用的是VC5的console程序。
0 error 0 warning
在我的k6-233上算12用了1分30秒。麻烦你再试试。:)
#include <stdio.h> 
const int MAX=12; 
char number[MAX+1]; 
void InsertNum(int n); 
void OutPut(); 
int main() 

  number[MAX]='\0';  
  InsertNum(1); 
  puts("OK"); 
  return 0; 

void InsertNum(int n) 

  bool End=false; 
  if(n==MAX) 
    End=true; 
  //number[n-1]=n+48;为写入文件方便,所以加了48 
  number[n-1]=n; 
  char temp; 
  for(int i=0;i<n;i++)
{
if(i)
{
temp=number[n-i];
number[n-i]=number[n-i-1];
number[n-i-1]=temp;
}
if(End)
OutPut();
else
{
InsertNum(n+1);
for(int j=0;j<n;j++)
number[j]=number[j+1];
}
}
}
void OutPut()
{
}
--
阿豪 [email protected]
最好的BCB学习网站 C++Builder开发网络(http://iamahao.yeah.net)
C++Builder 论坛(http://cppbahao.abc.yesite.com)
※ 修改:.mrcloud 于 Nov 12 12:03:42 修改本文.[FROM: 202.101.48.152]
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.101.48.152]

发信人: terran (terran), 信区: CLanguage
标  题: 斑竹,我的全排列来了!SURE WIN!
发信站: 网易虚拟社区 (Fri Nov 12 09:16:29 1999), 站内信件
抱歉,我用了自己的头文件,麻烦改一改.程序在我的机上通过了!
这次程序的算法和上次那个基本一样,只不过为了加快速度我用了数组!
另外,比较的时候,希望斑竹规定要用同样的I/O语句,因为程序里对速度影响
最大的除了算法,就是I/O语句了!
#include "myhead.h"
#define Max 8
int record[Max];
  
int repeat(int i);
main()
{
        int j;
        
        for(j=0;j<=Max;j++) record[j]=0;

for(j=1;j<=Max;j++)
{
record[1]=j;
repeat(1);
}
return ;
}
int repeat(int i)
{
int j,k,x,flag=1;
for(j=1;j<=Max;j++)
{
for(k=1;k<=i;k++)
{
if (record[k]==j)
{
flag=0;
break;
}
}
if(flag)
{
record[k]=j;
i++;
if(i<Max) repeat(i);
else
{
for(x=1;x<=Max;x++) printf("%d ",record[x]);
printf("\n");
}
if (j==Max) return 1;
record[k]=0;
i--;
}
flag=1;
}
}
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 210.75.56.43]

发信人: girlrong (阿蓉), 信区: CLanguage
标  题: 全排列结果补充
发信站: 网易虚拟社区 (Sat Nov 13 16:02:00 1999), 站内信件
    阿豪的新程序果然厉害,在我的P200MMX机器上去掉输出语句,用vc++6.0编
译成console程序,算11个元素全排列只花了56秒!不过老山羊的也只花56秒。你
们俩打个平手。至于terran的程序,非常遗憾,去掉输出语句后,10个元素全排
列也花了31秒,11个元素的全排列我没敢试,怎么也得几分钟吧。可能你的算法
还有待改进。jackyrong的不是c写的程序,我就没法试了。
    这些结果只是我在我的机器上实验的结果,因水平有限,难免有不对的地方
,仅供参考而已。
    
--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.243.60]


[关闭][返回]