c语言高手朋友们 进来帮个忙

我用易语言组合要20多分钟 太慢了 具体的做法是:
总共有3个步骤

第一步:
先将0123456789 一分为2 一共有252个组合
例如:12345 67890,13579 02468,12367 04589..........一共有252个组合
但是这里边有一半是变相重复的 去掉这些重复的:比如:
12345 67890,
67890 12345
上边组合刚好是前边跟后边重复 后边跟前边重复 这种情况刚好有一半 252/2=126
去掉重复的之后有126个组合

第二步:
然后用这126个组合再次排列 例如:
01234 56789
01234 56789
01234 56789

01234 56789
01234 56789
01235 46789

01234 56789
01235 46789
01234 56789

01234 56789
01235 46789
01235 46789

01235 46789
01234 56789
01234 56789

01235 46789
01234 56789
01235 46789

01235 46789
01235 46789
01234 56789

01235 46789
01235 46789
01235 46789
一直排列完所有组合
.总共有126*126*126=2000376个组合排列

第三步:
排列组合结束之后 直接保存到变量 变量名字就ppt吧
我要把这些代码调用到易语言里边 变量名字是ppt的话 方便我在易语言程序里边直接读取ppt里边的数据 这样能加快程序的运算速度 不要保存到文件的那种 从新调用的话就再次增加了程序运算速度和时间

我算了一下,到第二步后,结果只有126*126=15876种组合,是不是我的理解错了?
我的理解是:从0123456789中分出5个数后,另5个数也就定了,所以只有C(10,5)=252个,其中有一半是前后相同的,所以只有126个,两组126个再两两组合,共有126*126=15876.
按照这个思路,我写了一段程序,结果算一遍用不了一秒钟。
段程序很短小,20多行代码,是以函数的形式作的:
int getcomb(unsigned long ppt[]);
该函数返回组合的组数(即15786),调用之前先开辟一个无符号长整数数组ppt[15786],并将之作为参数供函数直接调用,调用完成后,ppt[]里即是根据上面所说的组合数据。
程序经过算法优化,效率相当高,我作了一下测试,在命令行方式下即便是五六年前的老机子也不会超过0.3秒,内存空间低于64k。由于是算法上的优化,不用C,其运算速度也不会慢到哪里去。
因不知这样的理解对不对,所以没有将代码帖出来,如果需要,即刻帖出。追问

谢谢你的帮助

排列组合以后数据有200376个组合 你理解的是:126*126=15876.
其实你理解的完全正确 只是 您少了一次126
完整的是这样 126*126*126=200376个组合
而不是126*126=15876
像3D的0~9选3的所有排列一个意思,3D的0~9的排列共有1000个组合,这里就像是126个2分组合选3的所有排列 一共有200376个组合

追答

因为没有接触过易语言,只好以C/C++语言的角度来处理。为了保证高效率,调用起来有些琐碎。
功能函数为int getcomb(char *ppt,unsigned int base[]);
调用及使用:
1、在调用该函数前,应开辟一块3*2000376字节的和一块216 int型的数组,以接受每组数据:
char *ppt=new char[2000376*3];
unsigned int base[216];
2、定义好了上述两个变量后,就可直接调用函数得到数据了:
getcomb(ppt,base);
3、如果想取第n个组合,按以下方式即可既得:
第n组合的第一个数;base[ppt[3*n]];
第n组合的第二个数:base[ppt[3*n+1]];
第n组合的第三个数:base[ppt[3*n+2]];
4、这些数据均以无符号长整数unsigned long (注:在32位系统里,unsigned long 与unsigned int是一回事)给出,虽然是10位数,但因效率的缘故,始终将0作为每一组的第一个数字,所以可能不显示,如显示678912345,其实是"06789 12345".
函数清单如下,后面附带作一个调用的例子:
int getcomb(char *ppt,unsigned base[])
{
unsigned char a,b,c,d,e,m;
int count,n;
char *pt;
count=0;
for(a=0;a125)break;
base[count]=b*100000000l+c*10000000l+d*1000000+e*100000;
n=10000;
for(m=0;m<10;m++){
if(m!=a&&m!=b&&m!=c&&m!=d&&m!=e){
base[count]+=m*n;
n/=10;
}
}
count++;
}
pt=ppt;
for(a=0;a<126;a++)
for(b=0;b<126;b++)
for(c=0;c<126;c++)
{
*pt++=a;
*pt++=b;
*pt++=c;
}
return count;
}
举例:提取第50028组的数据并显示,在32位系统下,C++:
void example(void)
{
char *ppt,
unsigned int num,base[126],
字数限制

温馨提示:答案为网友推荐,仅供参考
第1个回答  2013-05-06
>>先将0123456789 一分为2 一共有252个组合
我觉得不对吧。不考虑重复的情况下,第一位有10个可能的数值(0~9),第二位有9个可能,第三位有8个可能,以此类推,总共有10*9*8....*2*1(即10的阶乘)=3628800个可能值。不知道我的推断是否正确。
如果有3628800个数值的话,每个数值在源代码里算作13个字符(加逗号/换行符),总共47174400字节(47M)。如果每个数值在执行代码中算作8个字节,共29030400字节(29M)。
第二步的排列,没有看懂,能再解释一下吗?追问

你的意思我明白 你是按有序排列了 有序排列是多了点
我的意思是无序排列 无序排列就没那么多了
例如:01234 56978无序(这样只有252 去掉重复的有126)
再如:20134 96857有序(这样是很多的)
第二部是第一步完成后 按你理解的第一步的排列思路用到第二步就对了

追答

不懂无序排列,等其他高手。

第2个回答  2013-05-19

你这个再次组合是什么意思? 怎么那么多重复的? 126*126*126表示什么意思?

跟“湿润的风”分析一样,两组都为126个字符串,完全重新组合也只有126*126=15876种。

下面是我文库里一篇文章中代码改了下,可以达到楼主的要求。如果不显示,一秒不到就运行完了。

 

#include<stdio.h>
#include<string.h>
#define DISPLAYRESULT 1 //控制是否显示结果
void BFS(char s[], int n); //主要功能的实现函数声明:宽度优先遍历
char result[10]="01234"; //保存子集的字符数组
char leftHalf[10]="56789";
int count=0; //子集个数计数器
int lcount=0; //另一半计数器
int level=0; //保存当前路径长度
char sAll[126][6]; //一半长为5的
char sLeft[126][6]; //另一半
char ppt[126*126][11]; //最终结果
int main()
{
int i,j,k;
char str[]="0123456789";
int len =strlen(str);
for ( i=0;i<= len/2;i++)//依次输出'0','1','2','3','4'为根的所有子树的遍历结果
{
BFS(str+i, strlen(str+i));
}
//重新组合
i=0;j=0;k=0;
for (i=0;i<126;i++)
{
for (j=0;j<126;j++)
{
strcpy(ppt[k],sAll[i]); //双重循环进行重新排列组合
strcat(ppt[k]+5,sLeft[j]);
#if DISPLAYRESULT
if(1) printf("%05d#:%s\n",k+1,ppt[k]);
#endif
k++;
}
}
printf("共有结果%d种\n",k);
return 0;
}
//深度优先遍历算法。递归实现。
void BFS(char s[], int n)
{
if(s==NULL || n<=0 ||strlen(s)==0) return; //参数合法性判断
result[level]=s[0]; //保存当前路径上最后一个点
result[level+1]='\0'; //添加字符串结束符
level++; //路径长度加1
//count++; //计数器加1
if(level==5)
{
if(result[0]=='0') //含'0'的长为5的字符串,存入result中
{
sprintf(sAll[count],"%s",result);
count++; //计数器加1
#if DISPLAYRESULT
printf("%3d(%2d): %s\n",count,level,result);//输出当前路径上的字符串
#endif
}
else{ //另外五个字符,存在sLeft中
sprintf(sLeft[lcount],"%s",result);
lcount++; //计数器加1
}
}
for(int i=1;i<n;i++) //对所有子树执行本算法
{
BFS(s+i,n-i);
}
level--; //回退。很重要!以便之后处理上一层其他子树
return ;
}

追问

126*1216*126=200376个组合的意思是:126就是有126个0~9的2分,如:01234.56789,12356,04789...............等 一共有126个2分的排列,
然后这126个2分的排列 分别用126个排列*126个排列*126个排列=200376个新的排列组合,
最像的就是像3D的0~9选3的所有排列一个意思,3D的0~9的排列共有1000个组合,这里就像是126个2分组合选3的所有排列 一共有200376个组合。详细的请您再看一次上边我的叙述

谢谢你

追答

明白了。修改后的代码看附件,种数符合。除了不知道楼主需要怎么分隔。全部都是字符串,共126*126*126=200376种组合,同样数量的字符串。结果在ppt数组里。

明白了,修改后的程序看附件。用200376个元素的字符串数组ppt保存结果。

追问

很感谢 我昨天试了下 原来我不会运行这个代码 不知道怎么运行它得到他的数据 能否帮忙直接做成dll 谢谢了

第3个回答  2013-05-19
你最后的数据要什么格式的?二维数组?ppy[i][j],i=0~2000375,j=0-5,表示第i组第j个串?
第4个回答  2013-05-08
便我在易语言程序里边直接读取
第5个回答  2013-05-05
用VB做行么?追问

vb 不知道速度怎么样 据说vb是易语言的英文版 如果能达到秒杀 当然用什么都是一样的 vb其实对我来说更好 易语言能直接使用vb的源码 不用再转换了

相关了解……

你可能感兴趣的内容

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 非常风气网