排列组合算法

2014-11-24 10:10:40 · 作者: · 浏览: 1

排列组合算法

排列算法:

排列算法采用递归思想很简单。如1,2,3,4我们求其排列。

首先遍历1,2,3,4.

遍历1,剩下2,3,4递归处理

遍历2,剩下1,3,4递归处理

遍历3,剩下1,2,4递归处理

遍历4,剩下1,2,3递归处理

我们的目标是把相应的排列给答应出来,所以这个时候需要一个数组来保存已经处理的数字。但是关于数组的下标在递归的时候是个问题,我们改采取怎样的方式呢?可以发现这里有一个技巧,用原始数组的长度减去当前待处理的数组的长度就得到元素的数组索引。如刚开时候是1,2,3,4。数组长度等于原始数组长度,所以1的索引是0。处理1之后,剩下2,3,4,此时数组长度是3,所以我们把2的数组索引定义为4-3=1。以此类推,直到数组的长度为1。

组合算法:

组合的思想和排列一样,只不过组合之间的元素不需要前后前后顺序要求,所以我们需要排除在排列中重复的元素。关于去除的思想,我们在这里可以采取一种简单的方法,我们将组合的元素按顺序排列,保证后面的元素大于前面的元素,这样就可以实现无重复了。

如,我们这样处理:

1,2;

1,3;

1,4;

2,3;

2,4;

3,4;

这样按照从小到大的顺序从而实现了无重复的排列。

关于组合,稍微麻烦的是在处理数组的元素下标,想了好久想到到了一个比较拙劣的办法,实属本人不才。我在函数的参数列表中加了一个参数k,来表示数组元素下标。当采用递归的时候,说明要产生下一个数组元素,所以k++,递归调用完毕后,我们要依次遍历后面的元素,所以要k--。

实现代码:

一个三个函数按照顺序分别表示的是:,,的算法。

#include
  
   
#include
   
     #include
    
      using namespace std; void arrangeN(list
     
       &Lis,vector
      
        &Vec); void arrangeK(list
       
         &Lis,vector
        
          &Vec,int nK,int nN); void combineK(list
         
           &Lis,vector
          
            &Vec,int nK,int nN,int k); void main() { int n1 = 10; list
           
             Arra; vector
            
              Vec(n1); //for(int i=1;i<=n;i++) // Arra.push_back(i); //arrangeN(Arra,Vec); int n2 = 5; int nk = 4; for(int i=1;i<=n2;i++) Arra.push_back(i); //arrangeK(Arra,Vec,n2,n2); combineK(Arra,Vec,nk,n2,0); } void arrangeN(list
             
               &Lis,vector
              
                &Vec) { list
               
                ::iterator iter; int nSize = Lis.size(); int nLength = Vec.size(); for(iter = Lis.begin();iter != Lis.end();iter++) { Vec[nLength-nSize] = *iter; if(nSize == 1) { for(int i=0;i
                
                  Lisc(Lis); Lisc.remove(*iter); arrangeN(Lisc,Vec); } } void arrangeK(list
                 
                   &Lis,vector
                  
                    &Vec,int nK,int nN) { list
                   
                    ::iterator iter; int nSize = Lis.size(); for(iter = Lis.begin();iter != Lis.end();iter++) { Vec[nN-nSize] = *iter; if(nN-nSize +1 == nK) { for(int i=0;i
                    
                      Lisc(Lis); Lisc.remove(*iter); arrangeK(Lisc,Vec,nK,nN); } } void combineK(list
                     
                       &Lis,vector
                      
                        &Vec,int nK,int nN,int k) { int nSize = Lis.size(); list
                       
                        ::iterator iter; for(iter = Lis.begin();iter != Lis.end();iter++) { if(nN - nSize == 0) k = 0; Vec[k] = *iter; if( k + 1 == nK) { for(int j=0;j
                        
                          Lisc( ++iter,Lis.end() ); iter--; k++; combineK(Lisc,Vec,nK,nN,k); k--; } } } 
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
        
       
      
     
    
   
  

测试结果:

4!

\

A(5,2)

\

C(5,3)