也论全排列的递归实现

来源:互联网 发布:nvslp监控软件下载 编辑:程序博客网 时间:2024/05/29 12:44

今天在专栏里看到这样一个帖子

http://blog.csdn.net/morewindows/article/details/7370155

举了一个题目是这样的

用C++写一个函数, 如 Foo(const char *str), 打印出 str 的全排列,
如 abc 的全排列: abc, acb, bca, dac, cab, cba

 

但是对于该帖子关于全排列递归实现的思路理解起来总是觉得很别扭,怪怪的。所以就根据自己的理解,

自己写了个函数。

一、递归函数

我理解的递归函数就是  f(n)=Pf(n-1) //P表示某种方法的转换

                   f(1)=X      //X为解决方法的确定值

满足这样的条件,那么就可以通过f(1)的值,解决f(n)的问题了。

二、关于字符串全排列的理解

字符串abc的全排列结果为:

为   abc

     acb

     bac

     bca

     cba

     cab

可以发现全排列的规律就是 abc 把: a拿出来然后字符串bc进行全排列,然后按顺序把b拿出来ac进行全排列,最后再把c拿出来字符串ab进行全排列。

按照开始对递归函数的理解,写出的表达式为

    RN表示一个字符  f(R1R2R3...RN)  为字符串  R1R2R3....RN的全排列

    结果:    f(R1R2R3...RN)=R1f(R2R3...RN)

             f(RN)=RN      //只有一个字符的时候RN自己就是自己的全排列

 

三、算法

   根绝上面的理解,那么算法就很容易写出来了

#include "stdafx.h"
#include "stdio.h"
#include "iostream"
#include "string"
void swap(char &a ,char &b)  //字符移位函数

    char m ; 
    m = a; 
    a = b; 
    b = m; 
}  
bool isSwap(char * str,int i,int k)//出来字符串中有重复字符出现的情况
{        
 for(int p=k;p<i;p++)
  {
   if(str[p]==str[i])
   return false;
  }
  return true;
}
void allrange(char * str,int k,int m)//全排列的递归函数
{
  if(k==(m-1))
 {
  printf("%s\n",str);
 }
 else
 {  
  for(int i=k;i<m;i++)
  {
    if(isSwap(str,i,k))
   {
        swap(str[i],str[k]);
        allrange(str,k+1,m);
        swap(str[i],str[k]);
   }
 
  }
 }
}
int _tmain(int argc, _TCHAR* argv[])
{   char str[100];
   while(1)
   {
    printf("%s","请输入要全排列的字符串:\n");
    std::cin>>str;
    printf("%s","全排列的结果为:\n");
    allrange(str,0,strlen(str));
 
   }
 return 0;
}

四、运行效果

 

五、总结

  在上面的算法中还考虑到了有重复字符出现的情况,

  如  abb这种字符串 递归的流程是 先把a拿出来然后字符串bb进行全排列,再把b拿出来,ab进行全排列,

最后一步将第三个字符串b拿出来ab进行全排列,这样就重复了。解决的方法就是每取一个字符的时候,都让

这个字符前面的字符与其比较,如果想当那就不用进行操作了。

   bool isSwap(char * str,int i,int k)//出来字符串中有重复字符出现的情况

此函数就是解决这个问题的。添加的这个函数,那么比如上面abb这个问题的时候,当按照算法取第三个字符

也就是b的时候,会跟前面两个字符一次比较,由于第二个字符也是b,所以就不进行操作了,也就解决的字符串

中有重复字符的问题。

 

 

原创粉丝点击