按字典序从小到大输出字符串的全排列,白书的7.2刚好讲到生成可重集的排列,所以参考白书上的代码写了个函数,具体操作过程是先将字符串中的所有字符按字典序排序,然后调用print_permutation( len, s, a, 0)即可。
void print_permutation( int len, char *P, char *A, int cur)
{
if( cur == len) {
for( int i = 0; i < len; i ++) printf( "%c", A[i]);
printf( "\n");
}
else for( int i = 0; i < len; i ++) //在A[cur]中填入p[i]
if( !i || P[i] != P[i-1])
{
int c1 = 0, c2 = 0;
for( int j = 0; j < cur; j ++) if( A[j] == P[i]) c1 ++;
for( int j = 0; j < len; j ++) if( P[i] == P[j]) c2 ++;
if( c1 < c2)
{
A[cur] = P[i];
print_permutation( len, P, A, cur + 1);
}
}
}
上面的c1是统计A[0]到A[cur-1]中p[i]的出现次数,c2则是P中p[i]的个数。当c1<c2时,我们就能递归调用这些函数。
另外值得注意的是枚举的下标i应不重复、不遗漏的取遍所有的P[i]值,因为P经过排序,所以我们只需要不断P[i]与P[i-1] 是否相等就知道是不是重复了。
完整的程序如下:
#include<cstdio>
#include<cstring>
#include<cstdlib>
char s[15], a[15];
int len;
int cmp( const void *_p, const void *_q)
{
char *p = ( char *)_p;
char *q = ( char *)_q;
return *p - *q;
}
void print_permutation( int len, char *P, char *A, int cur)
{
if( cur == len) {
for( int i = 0; i < len; i ++) printf( "%c", A[i]);
printf( "\n");
}
else for( int i = 0; i < len; i ++)
if( !i || P[i] != P[i-1])
{
int c1 = 0, c2 = 0;
for( int j = 0; j < cur; j ++) if( A[j] == P[i]) c1 ++;
for( int j = 0; j < len; j ++) if( P[i] == P[j]) c2 ++;
if( c1 < c2)
{
A[cur] = P[i];
print_permutation( len, P, A, cur + 1);
}
}
}
int main()
{
int tt;
scanf( "%d", &tt);
while( tt --)
{
scanf( "%s", s);
len = strlen( s);
qsort( s, len, sizeof( char), cmp);
memset( a, 0, sizeof a);
print_permutation( len, s, a, 0);
printf( "\n");
}
return 0;
}
用C++的库函数:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int T;
scanf( "%d", &T);
char s[15];
while( T --)
{
scanf( "%s", s);
int len = strlen( s);
sort( s, s + len);
do
{
printf( "%s\n", s);
}while( next_permutation( s, s + len) );
printf( "\n");
}
return 0;
}
参考一个大牛的写法:
#include<cstdio>
#include<cstring>
#include<cstdlib>
char s[15], a[15];
int len;
int cmp( const void *_p, const void *_q)
{
char *p = ( char *)_p;
char *q = ( char *)_q;
return *p - *q;
}
void dfs( int cur)
{
if( cur == len)
printf( "%s\n", a);
else for( int i = 0; i < len; i ++)
if( !i || s[i] != s[i - 1])
{
int c1 = 0, c2 = 0;
for( int j = 0; j < cur; j ++) if( a[j] == s[i]) c1 ++;
for( int j = 0; j < len; j ++) if( s[i] == s[j]) c2 ++;
if( c1 < c2)
{
a[cur] = s[i];
dfs(cur + 1);
}
}
}
int main()
{
int tt;
scanf( "%d", &tt);
while( tt --)
{
scanf( "%s", s);
len = strlen( s);
memset( a, 0, sizeof a);
qsort( s, len, sizeof( char), cmp);
dfs( 0);
printf( "\n");
}
return 0;
}