题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印由字符abc所能排列出来的所有字符串abc,acb,bac,bca,cab,cba.
问题解析:
(1)求所有可能出现在第一个位置的字符,即把第一个字符和后面的所有字符进行交换。
(2)固定第一个字符,求后面的排列。
(3)仍然可以把后面的分成第一步和第二步。
以abc 为例:
(1)a b c a和自己进行交换,此时固定a,然后求后面b和c的排列
(2)a b c b和自己进行交换, 此时固定b,求c的排列
(3)a b c c和自己进行交换,固定c,但后面已没有排列,输出
(4)a c b 返回(2)b和c进行交换,固定c求后面b的排列,和(3)类似,输出
(5)b a c 返回(1)a和b进行交换,固定b求后面的排列
后面的基本操作都类似,最后输出abc acb bac bca cab cba
以下是代码:
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
//字符串全排列
/*将开头第一个字符先与每一个后面的字符进行交换
固定开头字符,求后面字符组合
后面字符重复上面的步骤,直到下一个字符为空*/
void Permutation(string &s, int pbegin)
{
if (s[pbegin] == '\0')
{
cout << s << endl;
}
for (int pch = pbegin; s[pch] != '\0'; pch++)
{
char temp = s[pch];
s[pch] = s[pbegin];
s[pbegin] = temp;
Permutation(s,pbegin+1);
temp = s[pch];
s[pch] = s[pbegin];
s[pbegin] = temp;
}
}
int main(void)
{
string s;
cin >> s;
Permutation(s,0);
return 0;
}
全组合
基本思想: 如果输入n个字符,则这n个字符能构成长度为1,2,...,n的组合。在求n个字符的长度为m(1<=m<=n)组合的时候,我们把这n个字符分成两部分:
第一个字符和其余的所有字符。
如果组合里包含第一个字符,则下一步在剩余的字符里选取m-1个字符;
如果组合里不包含第一个字符,则下一步在剩余的n-1字符里选取m个字符。
也就是说:我们可以把求n个字符组成长度为m的组合的问题分解成两个子问题。
(1)分别求n-1个字符中长度为m-1的组合
(2)分别求n-1个字符中长度为m的组合。
什么意思呢?
举个栗子:
a b c
n为3,求长度为1的组合
先将a放进去 a b c ,求后面为0的组合,就直接输出a
往后移,将a取出 a b c,求后面长度为1的组合
现在移到字符b上(将a不放进去,b在里面),求后面长度为0的组合,直接输出b
往后移b,(将b取出) c,求后面长度为1的组合
现在移到c上(将b不放进去),求后面长度为0的组合,直接输出c
往后移为空,返回。
后面基本类似。
算法代码:
//全组合
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
#include<assert.h>
void Combination(char *string, int number, vector<char> &result);
void Combination(char *string)
{
assert(string != NULL);
vector<char> result;
int i, length = strlen(string);
//分别求出长度为1,2,...,n的组合
for (i = 1; i <= length; ++i) //用for循环分开字符组合
Combination(string, i, result);
}
void Combination(char *string, int number, vector<char> &result)
{
assert(string != NULL);
if (number == 0)
{
static int num = 1;
printf("第%d个组合\t", num++);
vector<char>::iterator iter = result.begin();
for (; iter != result.end(); ++iter)
printf("%c", *iter);
printf("\n");
return;
}
if (*string == '\0')
return;
result.push_back(*string);
//string+1表示n-1的字符
Combination(string + 1, number - 1, result);//把当前第一个字符放到组合之中
result.pop_back();
Combination(string + 1, number, result);//把当前第一个字符不放到组合之中
}
int main(void)
{
char str[] = "aab";
Combination(str);
system("pause");
return 0;
}