永发信息网

c语言 重复字符全排列

答案:2  悬赏:0  手机版
解决时间 2021-02-28 23:01
  • 提问者网友:城市野鹿
  • 2021-02-28 05:44
要求按升序输出。我的程序如下。一是不解为什么有的不是按升序输出的,比如输入1234,;另一个是怎么实现具有相同重复字符情况下的全排列。别如把aabb全排列,是6种情况而不是24种。求指导~谢谢~
# include
# include
char s[100];
int n = 0;

void swap(char *a, char *b)
{
char m;
m = *a;
*a = *b;
*b = m;
}
void circle_right(char a[],int m,int i)
{
char temp;
int j,k;
for(k=1;k<=i-m;k++)
{
temp=a[i];
for(j=i;j>m;j--)
{
a[j]=a[j-1];
}
a[m]=temp;
}
}
void circle_left(char a[],int m,int i)
{
char temp;
int j,k;
for(k=1;k<=i-m;k++)
{
temp=a[m];
for(j=m;j {
a[j]=a[j+1];
}
a[i]=temp;
}
}

void perm(int k,char a[],int l)
{
int i;
if(k == 1)
{
for(i = 0; i < l; i++)
printf("%c", s[i]);
printf("\n");
n++;
return;
}
for(i = 0; i < k; i++)
{
swap(&a[0], &a[i]);
circle_right(a,1,i);
perm(k-1,&a[1],l);
circle_left(a,1,i);
swap(&a[i], &a[0]);

}
}
int main()
{
int l;
gets(s);
l=strlen(s);
perm(l,s,l);
printf("total:%d\n", n);
return 0;
}
最佳答案
  • 五星知识达人网友:舊物识亽
  • 2021-02-28 06:21
给程序加点注释,让别人也稍微明白一下
呵呵,你确定自己的程序在思想上之类的没有错误么?
在perm后面的for中调用circle_*的函数的时候,你传入的l总是会比i大的
这样一来在函数中m接收l,i接收i
然后再circle_*中的for循环的判断条件是i-m应该是不会执行吧

至于你说的那个功能我也不是很清楚
呵呵,能帮的就只有这些了
全部回答
  • 1楼网友:長槍戰八方
  • 2021-02-28 07:32

递归就是不停地保存跳转时的状态和恢复跳转前的状态的操作。

就拿你的例子来说吧。

*(w+n-1)=*(s1+i);

    *(s1+i)=*s1;

    *s1=*(w+n-1);

等同于

w[n-1]=s1[i];

s1[i]=s1[0];

s1[0]=w[n-1];

相当于把w[n-1],s1[i]的,s1[0]值进行转换。

    第一次转换的结果是w[1]=a,i=0,s1="abc",这个时候保存当前的状态(第一层递归),跳转执行递归函数(第二层递归),s1+1是的递归函数的s指向s1[1],即b的地址,n-1=1,n不小于1,继续for循环。

    第二次转换的结果w[0]=b,i=0,s1="bc",这个时候保存当前的状态(第二层递归),跳转执行递归函数(第三层递归),s1+1是的递归函数的s指向s1[2],即c的地址,n-1=0,n小于1,输出w数组的值,即ba,执行完成本次跳转。

    然后返回第二层递归的状态,此时s1="bc",i=0,i自加后等于1,* (s1+i)的值为c,执行交换操作,再次执行跳转操作(第三层递归),结果为w[0]=c,i=1,s1="cb",n-1=0,n小于1,输出w数组的值,即ca,执行完成本次跳转。

    然后返回第二层递归时的状态。继续执行跳转前的for循环。此时i=1,自家后等于2,s1的长度是2,所以*(s1+2)的值为0(字符串的默认结束符号),所以本次循环截止,跳回第一重循环。

   以此类推,直至第一重循环也结束。递归全部结束。

我要举报
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息
大家都在看
推荐资讯