(先稳定一下军心,下面所有代码都测试过,可以直接用,所以就没有截图,想看效果的可以自己运行一下)
1.全排列
全排列:字符以任意顺序排列,比如123的全排列是123,132,213,231,312,321。长度为n的字符串的全排列个数为n!个,下面是代码:
/*思路:s全排列是第一位与s[1~n-1]的全排列,所以每次交换第一位与
** s中的某一位,然后递归求出s[1~n-1]的全排列。
*/
#include
#include
using namespace std;
static int count=0;
void Permutation(string s,int beg,int sLen)
{
if(0==sLen) //这轮全排列结束
{
++count;
cout<>s;
int sLen=s.size();
Permutation(s,0,sLen);
cout<
void Permutation(string s,int beg,int end)
{
if(beg==end-1) //这轮全排列结束
{
++count;
cout<
在上面的代码中,如果字符串中有重复的字符,就不能避免重复输出了。例如对于1213,n!=4!=24,如果考虑到避免重复输出,应该有4!/2!=12个。下面的代码是避免全排列中的重复输出:
/* 思路:1.轮流选取s中的每位作为第一位。如果第i位字符在[0,i-1]这个区间内出现过,
** 就不再对其进行排列,因为把它放在第一位的所有排列在前面排列过了(就是代码中j作为循环变量的作用)。
** 2.把当前选取的这一位放入目标数组中。
** 3.用一个临时数组保存剩余的字符,并把其作为源。同时目标数组的地址下移一位,因为当前位已经排列好。
*/
#include
#include
using namespace std;
static int count=0; //记录全排列个数
char *result=new char[16](); //存放某个排列
void Permutation(string strSource,char *strResult,int sLen)
{
if(sLen==1) //这轮全排列结束
{
strResult[0]=strSource[0]; //只有一个字符
++count;
//strResult在递归的过程中是一次向后移一位的,所以字符串的首地址是result
cout<>s;
int sLen=s.size();
Permutation(s,result,sLen);
cout<
2.排列
在第一节中讨论了字符串全排列的问题,在这一节讨论排列的问题。
排列:从长度为n的字符串中任意挑选m个元素以任意次序排列。全排列是n=m的特殊情况。
编程思路和上面的代码很像。最大的不同之处就是把结束时的情况放到了for循环里面,并且把return去掉了,这是为了保证所有的情况都能遍历到。还增加了一个参数k来记录已经取得的字符个数。
#include
#include
using namespace std;
static int count=0; //记录全排列个数
char *result=new char[16](); //存放某个排列
//sLen是源字符串的长度,m是要取的字符个数,所以排列个数是A(sLen,m)
//k为已经取得的字符个数
void Permutation(string strSource,char *strResult,int sLen,int m,int k)
{
for (int i=0;i>s;
cout<<"请输入m:";
cin>>m;
int sLen=s.size();
if(m<=sLen)
Permutation(s,result,sLen,m,0);
cout<
这个代码和上面的代码很像,这里可以好好体会一下这两个代码的不同之处。为了和数学中的排列定义A(n,m)相符,我把代码中的n换成了m,sLen相当于这里的n 。还需要说明的一点就是这段代码只能运用在无重复字符的字符串中,若有重复字符,会有重复输出。