字符串的全排列

问题如下:
给定字符串,比如char *s = "abc",请用里面的字符做全排列,即求'a','b,'c'的全排列,其结果应该是"abc","acb","bac","bca","cab","cba"一共六种.
这个问题比较容易想到的解决方案是使用递归,要求以'a'开头的"abc"的全排列,可以先求"bc"的全排列,然后再加上'a'即可,"bc"一共有两种全排列,"bc","cb"故以'a'开头的全排列就是"abc","acb",以此类推,再分别求出以'b','c'开头的全排列即可.故归纳起来算法如下:

void Permute(strInput,strOutput,recursLev)
1 n <- length(strInput)
2 if recurLev = n
3      then print strOutput;
4      return;
5 for i <- 0 to n
6      do if strInput[i] has been used //used[i]
7          go to step 5, operate the next characater.
8      else
9          do strOutput[recursLev] <- strInput[i]
10        used[i] <- 1
11        Permute(strInput,strOutput,recursLev+1)
12        used[i] <-  0

下面是我用C实现的上述算了,增加了一个包装类,分配了三个数组并对输入字符串做了一些处理.

int Permute(char inString[])
{
     int length,i,*used;
     char *out;

     length = strlen(inString);
     out = (char *)malloc(length +1);
     if(!out)
     return 0;

     out[length] = '\0';
     used = (int *)malloc(sizeof(int) * length);
     if(!used)
     return 0;
     for(i = 0;i    {
        used[i] = 0;
    }

    DoPermute(inString,out,used,length,0);
    free(out);
    free(used);
    return 1;

}

 void DoPermute(char in[],char out[],int used[],int length,int recursLev)
{
     int i;
     if(recursLev == length)
     {
          printf("%s\n",out);
          return;
     }
   for(i = 0; i   {
        if(used[i])
              continue;
        out[recursLev] = in[i];
        used[i] =1;
        DoPermute(in,out,used,length,recursLev+1);
        used[i] = 0;
    }
 }
 
上面的代码不能正解处理字符串中有重复字符的情况,即输出结果有可能有重复.如果字符串中有重复字符,可以先对字符串里面的字符进行排序,然后再调用DoPermute函数.只要对DoPermute方法做一点小小的改动即可,添加一辅助变量用以记录前一步操作的字符并与当前字符比较,如果当前字符与之不同并且还未被使用,则对其进行全排列

void DoPermute(char in[],char out[],int used[],int length,int recursLev)
{
     int i;

     char preChar;

     if(recursLev == length)
     {
         printf("%s\n",out);
         return;
     }
     preChar = 0;
     for(i = 0; i     {
          if(used[i] ==0 &&in[i]!=preChar)
          {
                  preChar = in[i];
                  out[recursLev] = in[i];
                  used[i] =1;
                  DoPermute(in,out,used,length,recursLev+1);
                  used[i] = 0;
           }
   
      }
 
}

 
 
 
 
posted @ 2007-04-29 14:51  芭蕉  阅读(2507)  评论(0编辑  收藏  举报