生成全排列、非全排列、组合

#include <stdio.h>

 

--- --- --- --- --- --- 生成全排列(递归) --- --- --- --- --- ---

参数解释:s[]:需要生成排列的数组,m:起始下标,n:结束下标
--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---

void perm(int s[],int m,int n)

{

    int i,t;

     if (m == n) //结束排列,输出

     {

         for(i = 0; i <= n; i++)  printf("%d ",s[i]);

         printf("/n");

     }

     else

         for (i = m; i <= n; i++)

         {    //把第i个元素换到起始位置

              t = s[i]; s[i] = s[m]; s[m] = t;

              perm(s,m+1,n); //除起始位置外,其他元素递归排列

              t = s[i]; s[i] = s[m]; s[m] = t; //位置复原

         }

}

 

 

--- --- --- --- --- -- 生成非全排列(递归) --- --- --- --- --- -

原理:与生成全排列相似,区别在于,取最后一个元素的时候,全排列

      只有一个可选元素,所以可以直接输出;而非全排列则需要从几

      个元素中选出一个,所以还要用循环把这些元素都取一次

参数解释:从下标mn的元素中取k个做排列

--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---

void permk(int a[],int m,int n,int k)

{  

    int i,j,t;

     if (k == 1 && m <= n) //递归到最后取一个的时候

     {

         for(i = m; i <= n; i++)

         {

              if(m > 0)  //输出前面排好的元素

                   for(j = 0; j <= m-1; j++)

                       printf("%d ",a[j]);

              printf("%d/n",a[i]); //输出最后一个

         }

     }

     else if(k > 1)

         for (i = m; i <= n; i++)

         {    //把第i个元素换到起始位置

              t = a[i]; a[i] = a[m]; a[m] = t;

              permk(a,m+1,n,k-1); //在剩下的元素中取k-1

              t = a[i]; a[i] = a[m]; a[m] = t; //位置复原

         }

}

 

 

--- --- --- --- --- ---  生成组合(递归) --- --- --- --- --- --- --- ---

原理:与计数排序类似,计数排序是每个元素与后面的比较,而组合是

      每个元素与其后面的元素组合,不考虑其前面的元素,以此避免重复。

      例:10个元素中取4个,则第1个元素的取值范围是下标0-6(因剩下的3

      元素只能在第1个元素的后面取,所以第1个元素后面必要至少还有3个元素)

      若第1个元素取下标0,则第2个元素的取值范围是下标1-7,……;

      若第1个元素取下标1,则第2个元素的取值范围是下标2-7,……;

      若第1个元素取下标3,第2个元素取下标5,则第三个元素的取值范围是

      下标6-8,……

参数解释:从数组a的,下标mn的元素中,

          k个放入数组t,其中这k个中的第一个放入t[s]  

--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---

void combine(int a[],int m,int n,int k,int t[],int s)

{  

    int i;

     if (k == 0) //结束组合,输出

     {

         for(i = 0; i < s; i++)

              printf("%d ",t[i]);

         printf("/n");

     }

     else

         for (i = m; i <= n-k+1; i++)

         {   

              t[s] = a[i]; //取出第i           

              combine(a,i+1,n,k-1,t,s+1);

         }    //i+1个开始一直到最后所有的元素中,取k-1

}

 

--- --- --- --- --- --- --- 调用 --- --- --- --- --- --- ---

void main()

{

    int a[5] = {1,2,3,4,5},t[3]={0};

    perm(a,0,4);          //全排列

    permk(a,0,4,3);       //(非全)排列

    combine(a,0,4,3,t,0); //组合

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值