首页 > 编程知识 正文

c语言整齐排列代码,排列组合代码实现

时间:2023-05-06 05:37:21 阅读:51450 作者:768

首先从递归实现来看,递归会逐步分解问题,所以比较容易理解,但需要消耗大量的堆栈空间,线程堆栈空间不够就无法执行,函数调用开销也很大。

(1)全排列:

所有数组是指按一定的顺序排列集合中的所有元素,使用p(n,n )=n! 表示n个元素的全部序列的个数。

例如,{1、2、3}的全部排列如下。

123; 132;

213; 231;

312; 321;

一共六个,也就是三个!=321=6。

这个是怎么算出的?

首先取一个元素,例如取出1,就剩下{ 2,3 }。

然后,从剩下的集合中取出一个元素,例如取出2,就剩下了{3}。

这样,如果一次取得所有能想到的情况,就成为如图所示的全部排列。

知道这个过程后,我也写了算法:

将数组视为一个集合,将集合分为0~s和s~e两部分。 其中0到s表示已经选择的元素,s到e表示尚未选择的元素。

按照perm(set,s,e )的顺序调用perm ) set,s 1,e )直到s (从e中选择一个要素并与s进行交换),也就是说,输出set )直到剩下的集合为空

c语言代码如下:

voidperm(intlist[],ints,inte,void ) cbk ) ) intlist[] ) inti; if(se ) ) cbk ) ) list; (else ) for ) I=s; i=e; I ) swap (列表,s,I ); perm(list,s 1,e,cbk ); swap (列表,s,I ); } }

其中:

voidswap(int*o,inti,intj ) {inttmp=o[i]; o[i]=o[j]; o[j]=tmp; } void CBK _ print (int * subs (printf ) ) ) ) ) ) ) ) ); for(inti=0; I

)2)组合:

组合是指从n个不同元素中提取m个元素合成的组,该组中的元素没有顺序。 从n个元素中取出k个元素的取法的数量用c(n,k )表示。

C(N,k )=n! //K! *(n-k )! )

例如,从{1、2、3、4}中取出的2个元素的组合如下。

12; 13; 14; 23; 24; 34

方法是先从集合中取出一个元素,例如取出1,{ 2,3,4 }剩下

然后,从剩下的集合中提取元素。 例如,取出2

此时12构成如图所示的组。

从以上过程可以看出,每次从集合中选择一个要素时,对剩下的集合(n-1 )进行k-1的组合。

COMB(set,subset,n,k ) )相反,从集合中选择一个元素,并将该元素放入subset中。 调用comb(set、subset、n-1、k-1 )直到仅选择一个元素}

c语言代码如下:

voidcombine(ints[],intn,intk,void ) CBK ) int*subset,intk ) ) if ) k==0) ) CBK ) subset,k ); 返回; }for(inti=n; i=k; I--}{subset[k-1]=s[I-1]; if(K1 )组合(s,i-1,k-1,cbk ); }else{cbk(subset,subset_length ); } }

任何递归算法都可以转换为非递归算法。 如果可以使用堆栈模拟函数保存调用中的参数就好了,当然,这样的方法没有什么意义,所以在这里就不讨论了。 这里介绍了用其他思路实现的非递归算法。

(1)全排列:

让我们先看看代码:

# include # includeusingnamespacestd; intmain () intmyints ) )={ 1,2,3 }; 出局了

此代码已通过STL Permutation。 应该注意的是第10行,首先对数组进行了排序。

第14行的next_permutation ()是STL函数,它生成当前列表中的下一个相邻词典序列表,其中的元素具有只能交换位置而不能更改数字的原理。

什么意思?

123的下一个词典顺序是132。 因为132比123大,但比其他顺序小。

算法是:

(1)从右向左,找到小于第一个右边数字的数字a。

)从右向左,找到大于第一个a的数字b。

)3)更换A和B。

)4)反转a之后的串(a除外)。

完成了。

现在,按照以上思路,我们来导出next_permutation函数。

templateboolnext_perm(t*start,T*end ) )/_ASM{int3}if ) start==end ) {returnfalse; }else{T*pA=NULL,*pB; T tmp=*end; //finda.for(t*p=end; p=start; p--}{if(p=start; p--}{if(p*pa ) ) {pB=p; 布雷克; }}//swap A,B.tmp=*pA; *pA=*pB; *pB=tmp; //flipsequenceafterafor (t * p=pa1,*q=end; p

(2)组合) 01交换法

如果使用0或1,则指示选定集合中是否存在元素。 因此,0/1列表可以表示选定的元素。

例如,如果[1 2 3 4 5],所选元素为[1 2 3],则列表为[1110]。

算法如下:

COMB(set,n,k ) ) (1)从左向右扫描0/1列表,遇到“10”组合时,转换为“01”。 )2)将在上一步中找到的“10”组合之前的所有1移动到set的最左边。 (3) (1) )2)重复,直到“10”的组合消失。 }

代码如下。

templatevoidcombine(Tset[] (,intn,intk,void ) CBK (tset ) ) ) unsigned char * vec=newunsignedchar (n ) n ); T*subset=newT[k]; //buildthe0-1vector.for(inti=0; I

对于其原因,n个位置处有k个1,根据算法移动可以确保k个1位置不重叠并且可以被n次复盖。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。