全排列算法解析(视频+详解+代码+STL)

全排列生成算法

刚开始自学的时候搜了两三个scdn中关于讲解全排列问题的博客,但是我理解能力比较差还是没有完全理解

,后来就在网上搜索了视频才完全弄懂,现在把我理解的分享给你们。

学习视频:http://v.ku6.com/show/RP7r6vew4Qb_MCF1eYZeOg...html

1、  没有重复字符的全排列问题

例如:对abcd进行全排列

如图:

分析:a b c d

1、  定a 对b c d进行全排列 

2、  定 b对a c d进行全排列

3、  定c 对a b d进行全排列

4、  定d 对a b c进行全排列

很明显这个涉及到递归的思想,

#include<iostream>
#include<cstring>
using namespace std;
char str[]="abcd";
void permitation(int from,int to)
{
       if(from==to)//相当于a->d后就输出
       {
              for(int i=0;i<=to;i++)
              {
                     cout<<str[i];//输出其中一种排列的情况
              }
              cout<<endl;
              return;//递归出口,结束当前递归,以便对接下来的进行全排列
       }
       for(int i=from;i<=to;i++)
       {
              swap(str[i],str[from]);//让首字母与其中的某个字符进行交换操作,例如上文中对的分析abcd的全排列中,
              //开始首字母是a,接下来是b,然后是c最后是d,这就涉及到swap操作,第一次因为from=0,i=0,自己交换自己之后就真正的交换
              permitation(from+1,to);
              swap(str[i],str[from]);//做完之后再交换回来,保证维系原来abcd的顺序,以便下一次进行全排列
    }
}
int main(){
    int size=strlen(str);//获得字符串长度
       permitation(0,size-1);
       return 0;
}

2、  出现重复字符的全排列问题

例如:1223

1-223

2-123

3-221

带重复字符的全排列就是每个字符分别与它后面非重复重现字符的进行交换

即:第i个字符与第j个字符交换时,要求[I,j)中没有与第j个字符相等的数出现

代码:(知识加了一个判断条件)

/*无重复字符情况的全排列问题*/

#include<iostream>
#include<cstring>
#include<algorithm>
using namespacestd;
char str[1000];
int isSwap(intfrom,int to)
{
       bool flag=true;
       for(int i=from;i<to;i++)
       {
              if(str[to]==str[i])
              {
                     flag=false;
                     break;
              }
       }
       return flag;
}
voidpermitation(int from,int to)
{
       if(from==to)//相当于a->d后就输出
       {
              for(int i=0;i<=to;i++)
              {
                     cout<<str[i];//输出其中一种排列的情况
              }
              cout<<endl;             
              return;//递归出口,结束当前递归,以便对接下来的进行全排列
       }
       for(int i=from;i<=to;i++)
       {
              if(!isSwap(from,i))
              continue;
              swap(str[i],str[from]);//让首字母与其中的某个字符进行交换操作,例如上文中对的分析abcd的全排列中,
              //开始首字母是a,接下来是b,然后是c最后是d,这就涉及到swap操作,第一次因为from=0,i=0,自己交换自己之后就真正的交换
              permitation(from+1,to);
              swap(str[i],str[from]);//做完之后再交换回来,保证维系原来abcd的顺序,以便下一次进行全排列
    }
}
int main(){
      
       while(1)
       {
              printf("Please input astring:");
              cin>>str;
              sort(str,str+strlen(str));
           intsize=strlen(str);//获得字符串长度
              permitation(0,size-1);
       }
       return 0;
}


3、  知道原理之后下次用的时候可以直接利用STL中的库函数来做,库函数不用考虑是否有重复字符出现特别方便

代码:

 

#include<iostream>
#include<cstring>
#include<algorithm>
using namespacestd;
char str[1000];
int main(){
      
       while(1)
       {
              printf("Please input astring:");
              cin>>str;
              sort(str,str+strlen(str));
              //从stl库中调用全排列的库函数
              do
              {
                     for(inti=0;i<strlen(str);i++)
                     {
                            cout<<str[i]<<"";
                     }
                     cout<<endl;
              }while(next_permutation(str,str+strlen(str)));
             
       }
       return 0;
}


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值