已知字符串中的字符是互不相同的,现在把他们任意排列(例如,若已知字符串是“ab”,则任意输出排列是“ab”“aa”“ba”“bb”),编程输出全部的所有组合。
不同于输出全排列,只需要在函数中设置首位和后面各位的循环递归即可。同以上思路要从“ab”中延伸出“aa”“bb”可通过将首位赋值给后面各位循环递归完成(需要一定的限制条件)。
/*
字符串的全排列
已知字符串的字符是互不相同的,现在把他们的任意排序(例如,若已知字符串“ab”,则任意排序为
“aa”“ab”“ba”“bb”)
*/
#include <iostream>
using namespace std;
void ArbitrarilyChar(char *s, char * Copy,int nFrom, int nEnd, int nT);
void strncpy(char * dest, char * src, int nStart, int nEnd);
int main()
{
char sInput[] = "abc";
char *Copy = new char [strlen(sInput)+1];
strncpy(Copy, sInput, 0, strlen(sInput)); //拷贝生产输入字符串的副本
ArbitrarilyChar(sInput,Copy,0,strlen(sInput)-1,strlen(sInput));
delete [] Copy;
cin.get();
return 0;
}
void ArbitrarilyChar(char *s,char * Copy,int nFrom,int nEnd,int nT)
{
/*
输出字符串的任意排列
输入参数:*s ---输入的字符串
*Copy ---输入字符串的副本,用于初值的校正
nFrom ---起始位置
nEnd ---截止位置
nT ---循环赋值次数
输出参数:
*/
int Num = nT;
if (nEnd<nFrom)
{
return;
}
else if (nFrom==nEnd)
{
for (int i = 0; i <=nEnd; i++)
{
cout << s[i];
}
cout <<" ";
}
else
{
for (int i = nFrom; i <= nEnd; i++)
{
if (nFrom==0)
//当一个首位的全部排列输出后,对原值进行校正
{
strncpy(s,Copy, 0, strlen(s));
cout << endl;
}
swap(s[i], s[nFrom]);
ArbitrarilyChar(s,Copy,nFrom + 1, nEnd, nT-1);
for (int j = 1; j< Num; j++)
//将首位循环赋值给后面各位完成衍生
{
if (nFrom<nEnd)
//仅在nFrom<nEnd时完成赋值
{
char temp = s[nFrom+j];
s[nFrom+j] = s[nFrom];
ArbitrarilyChar(s,Copy, nFrom + 1, nEnd, nT-1 );
s[nFrom+1]=temp;
}
}
}
}
}
void strncpy(char * dest, char * src, int nStart, int nEnd)
{
/*
字符串的拷贝
输入参数:*dest ---输入的字符串
*src ---待拷贝字符串
nStart ---起始位置
nEnd ---截止位置
输出参数:
*/
nEnd++;
while (nEnd--)
{
*dest++ = *src++;
}
}
运行结果
由于输入为“abc”的任意排列共有3的3次方共27个,而对其递归以a开头为例共会输出12个值,在赋值后的递归交换中可能会产生重复输出的现象,n(≧▽≦)n初学者解决不了,大家指点一下。