递归:递归法解决排列问题

来源:互联网 发布:castep 优化晶体结构 编辑:程序博客网 时间:2024/06/06 08:52

方法1:

程序大致结构:

约定:pl[len] //pl 为最终放置结果的数组;len为数组的长度

         ele为参与排列的个元素出现的个数

         i为pl中下标

假设参与排列的元素有ABCD

run(ele,int i){

    { 

     递归收敛判断;

     收敛后进行处理;

     }

      //递归块1

   {   若元素A的个数不为0;

          将元素A的个数减1;

          run (ele,i+1);

         将元素A的个数 加1;

     }

    

    //递归块2

   {   若元素B的个数不为0;

          将元素B的个数减1;

          run (ele,i+1);

         将元素B的个数 加1;

     }

    

 //递归块3

   {   若元素C的个数不为0;

          将元素C的个数减1;

          run (ele,i+1);

         将元素C的个数 加1;

     }

  ......

  / /递归块n

   {   若元素M的个数不为0;

          将元素M的个数减1;

          run (ele,i+1);

         将元素M的个数 加1;

     }

}

注意:在递归块内,不应对所传入的参数进行改变;每个递归块所得到的原始参数应保持一致。

举例:ABCDEF进行排列

        static int[] ele={1,1,1,1,1,1};//每个元素出现的个数static int len=6;排列的长度static char[] rst=new char[6];static  void run(int[] ele,int i){if(i==len){for(char c:rst)  System.out.print(c);System.out.print('\n');}if(ele[0]!=0){ele[0]--;// <span style="color:#ff0000;">对传入的参数改变了,所以必须在本块内进行恢复</span>rst[i]='A';run(ele,i+1);//<span style="color:#ff0000;">i本身没有改变</span>ele[0]++;//<span style="color:#ff0000;">对参数进行恢复</span>。}if(ele[1]!=0){ele[1]--;rst[i]='B';run(ele,i+1);ele[1]++;}if(ele[2]!=0){ele[2]--;rst[i]='C';run(ele,i+1);ele[2]++;}if(ele[3]!=0){ele[3]--;rst[i]='D';run(ele,i+1);ele[3]++;}if(ele[4]!=0){ele[4]--;rst[i]='E';run(ele,i+1);ele[4]++;}if(ele[5]!=0){ele[5]--;// 对传入的参数改变了,所以必须在本块内进行恢复rst[i]='F';run(ele,i+1);ele[5]++;//对参数进行恢复。}}

方法2:( 优化方法1)

程序结构:

 set 中存放全部复合类型ele

ele{

 Type x;//参与排列的数据类型

 int num ;//该元素可以出现的个数

len:存放排列的数组长度

参数说明:n为 集合set剩余n个元素中选择,实际没有参与运算,仅仅是为了增加程序的可读性。

                   i为存放排列的数组的下标

run(set,int n,int i){

          if(i==len){

               递归结束

             } else{


                for (Ele ele:set){

                        if(ele可用){

                               ele.num--;

                               run(set,n-1,i+1);

                              ele.num++;

           }

           }

 }

}

实例:

1234 中任取3个元素全排列

public class Main {static ArrayList<Ele> set =new ArrayList<Ele>();// 存放参与排列的元素的包装类型static int[] rst=new int[3];//存放排列
      
       //  <pre name="code" class="java">       //参与排列的元素的包装类
public static class Ele{ int num;//参与排列的元素
boolean slc;//用于控制该元素的个数,由于本例中个元素最多出现一次,故使用bool来控制 public Ele(int i, boolean b) { num=i; slc=b;// TODO Auto-generated constructor stub} }

        //核心程序static void selct(ArrayList<Ele> set,int n,int i){if(n==0){//<span style="color:#ff0000;">此处完全可以换成i==len来判断</span>for(int num:rst){System.out.print(num);}System.out.println("");}else{for(Ele ele:set){if(!ele.slc){  ele.slc=true;  rst[i]=ele.num;
                          <span style="font-family: Arial, Helvetica, sans-serif;">//从set中其他n-1个元素进行全排列,从排列的i+1号位置开始</span>  selct(set,n-1,i+1);  ele.slc=false;}}}   }public static void main(String[] args){
          //为参与排列的元素赋值,这里共有4个元素1234    for(int i=1;i<5;i++){        set.add(new Ele(i,false));       }    <pre name="code" class="java">               //从set中取3个元素进行全排列,从排列的0号位置开始
<span style="font-family: Arial, Helvetica, sans-serif;">                     selct(set,3,0);</span>
}}

0 0