题目描述:
例举字母全排列并打印的问题。
解题思路:
几个注意点:(1)字符串排序问题,符合A<a<B<b^^^。注意cmp的返回值是int,因此需要*10后返回;
(2)删除出现过的字母的问题。回溯做全排列,由于字符串长度最大为13,所以全部存结果排序后删除重复是不可行的,因为13!过大,同时对每个可能的结果串打标记也过大,不可行。考虑在回溯过程中做改动,删除回溯的每一层中重复穷举的情况,因此在回溯函数中设计局部标记数组,标记改字母位于该位置(每一层回溯对应一个字符所处的位置)是否已经穷举过了。
代码:
#include <stdio.h>
#include <stdlib.h>
#define LEN 14
char str[LEN], len, letter[LEN], tmp[LEN];
int f[LEN];
int cmp(const void *a, const void *b)
{
double a1 = (double)(*(char*)a);
double b1 = (double)(*(char*)b);
if( a1 <= 90.0)
a1 += 31.5;
if( b1 <= 90.0)
b1 += 31.5;
//printf("%c %c %lf %lf\n",*((char*)a),*((char*)b),a1,b1);
return (int)((a1- b1) * 10);
}
void permution(int num)
{
int i;
int flag[130] = {0};//标记递归这一层里,这个字母是否已经穷举过。
if(num == len)
{
if(strcmp(tmp,letter) != 0)
{
printf("%s\n",letter); //加下查重判断
strcpy(tmp,letter);
}
}
else
{
for(i=0;i<len;i++)
if(f[i]==0 && flag[str[i]] == 0)
{
letter[num] = str[i];
f[i] = 1;
flag[str[i]] = 1;
permution(num+1);
f[i] = 0;
}
}
}
main()
{
int n;
scanf("%d",&n);
while(n>0)
{
n--;
scanf("%s",str);
len = strlen(str);
//对str排序
qsort(str,len,sizeof(char),cmp);
//printf("str:%s\n",str);
memset(letter,0,LEN);
memset(f,0,LEN);
permution(0);
}
system("pause");
return 0;
}