从键盘读入实数
实例说明
用已知字符串 s 中的字符,生成由其中 n 个字符组成的所有字符排列。设 n 小于字符串 s 的字符个数,其中 s 中的字符在每个排列中最多出现一次。例如,对于 s[ ]=“abc”,n=2,则所有字符排列有:ba,ca,ab,cb,ac,bc。
实例解析
可采用递归方法来生成用字符串 s 中的字符生成由 n 个字符组成的字符排列。设程序用字符数组 w[ ]存储生成的字符排列。令递归函数为 perm(int n,char *s),其功能是用字符串 s 中的字符生成由 n 个字符组成的所有排列。其方法是从字符串 s 依次选用其中的每个字符填写到字符排列的第 n 个位置(w[n-1])中,然后通过递归调用生成由 n-1 个字符组成的排列。当一个字符被选用后,进一步递归调用时可选用的字符中应不再包含该字符。另外,当发现一个字符排列生成后,就不再递归调用,而是输出生成的字符列。综合以上的思路,函数 perm(int n, char *s)的算法如下。
[算法]函数 perm(int n, char *s)的算法
{
if(一个排列已经生成)printf("%s\n",w);
else
{
保存本层可使用的字符串;
依次选本层可用字符循环完成以下工作;
{
将选用字符填入正在生成的字符排列中;
形成进一步递归可使用的字符串;
递归调用;
}
}
}
程序代码
#define N 20
char w[N];
perm(int n, char *s)
{
char s1[N];
int i;
if(n<1)
printf("%s\n",w); /* 一个排列生成输出 */
else
{
strcpy(s1,s); /* 保存本层可使用的字符 */
for(i=0;*(s1+i);i++) /* 依次选本层可用字符 */
{
*(w+n-1)=*(s1+i);/* 将选用字符填入正在生成的字符排列中 */
*(s1+i)=*s1;
*s1=*(w+n-1);
perm(n-1,s1+1); /* 递归 */
}
}
}
main()
{
int n=2;
char s[N];
w[n]='\0';
clrscr();
printf("This is a char permutation program!\nPlease input a string:\n");
scanf("%s",s);
puts("\nPlease input the char number of permuted:\n");
scanf("%d",&n);
puts("The permuted chars are:\n");
perm(n,s);
puts("\nPress any key to quit...");
getch();
}
程序运行结果
归纳注释
在本例子中,当递归调用生成 0 个字符的排列时,一个字符排列已经生成。为保存本层次可使用的字符串,可引入一个字符数组。为存储进一步递归可使用的字符串,可做如下处理,因进一步递归可使用的字符总比本层次可使用的字符少一个字符,可把本层次正在选用的字符与其字符串中的首字符交换,而进一步递归可使用的字符串就是从次字符开始的字符串。