全排列

从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。

比如字符集{‘a’,‘b’,‘c’},共有3!种组合。

abc、bac、bca、acb、cab、cba。

我们可以发现后面五种情况都是可以通过第一种情况两两交换得到,通过分析我们可以推导出递归方式。

#include<iostream>
#include<string>
#include<string.h>
using namespace std;
int num=0;
void SWAP(string & str,int x,int y){  
    char c=str[x];
    str[x]=str[y];
    str[y]=c;
}
void perm(string & str,int Begin,int End){
    if(Begin==End){  
        cout<<++num<<' '<<str<<endl;
    }else{
        for(int i=Begin;i<End;i++){
            SWAP(str,Begin,i); //交换begin位置和 i 位置
            perm(str,Begin+1,End); // begin位置后移,递归
            SWAP(str,Begin,i);  //换回来
        }
    }
}
int main(){
    string str;
    cin>>str;
    perm(str,0,str.length());
    return 0;
}

 

如果输出全排列需要按照字典序的顺序输出的话,我们可以把结果暂存在一个容器里面,比如用set保存,它会默认按字典序排列,最后输出结果,一定是按字典序的顺序输出。

set默认具有去重功能,如果不想去重,那么可以选择使用multiset保存,这样不会去重。

在c++中有更简单的方法使用全排列,algorithm头文件里面封装了next_permutation,prev_permutation函数,用来计算全排列。使用方法如下:(默认去重,默认字典序。)

next_permutation:对于当前的排列,如果在字典序中还存在下一个排列,返回真,并且将下一个排列赋予当前排列,如果不存在,就把当前排列进行递增排序。

prev_permutation对于当前的排列,如果在字典序中还存在前一个排列,返回真,并且将前一个排列赋予当前排列,如果不存在,就把当前排列进行递减排序。

#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
char str[4]={'a','b','c','a'};
void pri(){
    do{
        printf("%c%c%c%c
",str[0],str[1],str[2],str[3]);
    }while(next_permutation(str,str+4));
}
int main(){
    pri();
    return 0;
}

原文地址:https://www.cnblogs.com/ISGuXing/p/10574135.html