递归与排列组合

问题:

实现全排列
这里写图片描述

输出长这样:

111,112,113,121,122,123,131,132,133,211,212,213,221,222,223,231,232,233,311,312,313,321,322,323,331,332,333,

Process exited after 0.05746 seconds with return value 0 请按任意键继续…

递归(我的视角)

这里写图片描述

递归实现的代码框架(伪代码)

//s相当于当前的层数 e相当于所有的层数 //list初始化就是一棵空的队列,不断的添加节点和删除节点 void perm(int
list[], int s, int e)) {
int i;
if(s < e) //注意:这里不应该用while 因为每一层只需要调用节点数个递归就行了,也就是说每一层只需要负责广度,深度由递归的调用去是实现
{

    for(i = s; i <= e; i++)
    {             
         add(set,i) 
         perm(list, s + 1, e);
         remove(set,i)   //add和move都是为了 保护现场,为了下一次平行节点的重新展开作准备

    }

//s++; //没必要 ,s++的工作其实就是纵向深入,这个工作由递归实现
} if(s>=e) { printf(set)

}

}

完整的代码(自己随便瞎写的 (^_^))

java实现



public class Pailie {

    final static int ee= 3;     //实现123的全排列


    void add(int[]o, int i,int s)
    {

        o[s] = i;


    }


    void remove(int []o, int i,int s)
    {

        o[s] = 0;


    }

    void perm(int []list, int s, int e)
    {



        //  printf("(s=%d)", s);   调试用
        if(s >e)
        {
            //把这个排列组合输出出来
            for(int ii = 0; ii <= e; ii++)
            {
                System.out.printf("%d", list[ii]);

            }
             System.out.printf((s == ee) ?",":"");


        }
        else  //纵深
        {
            for(int i = 1; i <= e+1; i++)
            {
                add(list, i,s);
                perm(list, s + 1, e);
                remove(list, i,s);
            }
        }
    }


    public static void  main(String argv[])
    {
        int list[]=new int[ee];
        int s=0,e=ee-1;
        Pailie a=new Pailie();
        a.perm(list,s,e);


    }
}

C/C++实现

#include <stdio.h>
#define ee 3     //实现123的全排列 实现1-ee的全排列


void add(int * o, int i,int s)
{

    o[s] = i;


}


void remove(int * o, int i,int s)
{

    o[s] = 0;


}

void perm(int *list, int s, int e) 
{     



     //  printf("(s=%d)", s);   调试用 
    if(s >e)     
    {   
    //把这个排列组合输出出来 
      for(int ii = 0; ii <= e; ii++)
    {
        printf("%d", list[ii]);

    }
       (s == ee) ? printf(",") : printf(""); 


    }
    else  //纵深    
    {         
        for(int i = 1; i <= e+1; i++)
        {             
             add(list, i,s);             
             perm(list, s + 1, e);             
             remove(list, i,s);         
        }
    }
}


int main()
{
    int list[ee]={0};
    int s=0,e=ee-1;
    perm(list,s,e);
    return 0;

}

参考文献

https://www.cnblogs.com/autosar/archive/2012/04/08/2437799.html

补充

1实现任意n位数的全排列

#include <stdio.h>
#define ee 3     //实现三位数的全排列 


void add(char * o, char i,int s)
{

    o[s] = i;


}


void remove(char * o, char i,int s)
{

    o[s] = 0;


}

void perm(char *list, char s, int e) 
{     



     //  printf("(s=%d)", s);   调试用 
    if(s >e)     
    {   
    //把这个排列组合输出出来 
      for(int ii = 0; ii <= e; ii++)
    {
        printf("%c", list[ii]);

    }
       (s == e+1) ? printf(",") : printf(""); 


    }
    else  //纵深    
    {         
        for(int i = 0; i <2; i++)
        {    



            if(i==0) 
             {

             add(list, '(',s);             
             perm(list, s + 1, e);             
             remove(list, '(',s);   
            }else
            {
                add(list, ')',s);             
             perm(list, s + 1, e);             
             remove(list, ')',s); 
            }   

        }
    }
}


int main()
{
    char list[ee]={0};
    int s=0,e=ee*2-1;
    perm(list,s,e);
    return 0;

}

输出

((((((,(((((),(((()(,(((()),((()((,((()(),((())(,((())),(()(((,(()((),(()()(,(()()),(())((,(())(),(()))(,(()))),()((((,()(((),()(()(,()(()),()()((,()()(),()())(,()())),())(((,())((),())()(,())()),()))((,()))(),())))(,())))),)(((((,)((((),)((()(,)((()),)(()((,)(()(),)(())(,)(())),)()(((,)()((),)()()(,)()()),)())((,)())(),)()))(,)()))),))((((,))(((),))(()(,))(()),))()((,))()(),))())(,))())),)))(((,)))((),)))()(,)))()),))))((,))))(),)))))(,)))))),

Process exited after 0.1733 seconds with return value 0 请按任意键继续…

2括号配对问题

//(基于上面的排列实现的,程序写的有点乱,凑合看吧,,ԾㅂԾ,,) 
#include <stdio.h>
#define ee 3     //实现三位数的全排列 
int leftsum=0;
int rightsum=0; 

void add(char * o, char i,int s)
{

    o[s] = i;


}


void remove(char * o, char i,int s)
{

    o[s] = 0;


}

void perm(char *list, char s, int e) 
{     



     //  printf("(s=%d)", s);   调试用
    if(leftsum>=rightsum&&leftsum<=3&&rightsum<=3)   //只有在左括号数 大于右括号数的前提下 才继续进行 
    {



    if(s >e)     
    {   
    //把这个排列组合输出出来 
      for(int ii = 0; ii <= e; ii++)
    {
        printf("%c", list[ii]);

    }
       (s == e+1) ? printf(",") : printf(""); 


    }
    else  //纵深    
    {         
        for(int i = 0; i <2; i++)
        {    



            if(i==0) 
             {     
             add(list, '(',s);
             leftsum++;              
             perm(list, s + 1, e);      
             remove(list, '(',s);
             leftsum--;        
            }else
            {
             add(list, ')',s);
             rightsum++;            
             perm(list, s + 1, e);             
             remove(list, ')',s);
              rightsum--;

            }   

        }
    }
}
}




int main()
{

    char list[ee]={0};
    int s=0,e=ee*2-1;
    perm(list,s,e);
    return 0;

}

输出

((())),(()()),(())(),()(()),()()(),
Process exited after 0.1185 seconds with return value 0 请按任意键继续…

猜你喜欢

转载自blog.csdn.net/qq_26769591/article/details/81412011