从昨天到现在一直在回顾字符串的全排列算法,之前简单地复习了不含重复字符的字符串全排列,所以这次想彻底解决该算法。关于不含重复字符的字符串全排列比较简单,直接用递归思路解决即可,简单代码如下:
template <class T>
void permute(T list[],int k, int m)
{
int i;
if (k==m)
{
for (i=0;i<=m;i++)
cout<<list[i];
cout<<endl;
}
for (i=k;i<=m;i++)
{
//if (list[k]!=list[i]&&i!=k) //方法1:如果不同位置上的字符不相同,则进行交换
//{
// if ( IsSwap(list+i,list+m))//方法2:如果从该字符起,在区间[pBegin , pEnd)上没有重复字符,则进行交换,参考http://blog.csdn.net/hackbuteer1/article/details/7462447
// {
lswap(list+k,list+i);
permute(list,k+1,m);
lswap(list+i,list+k);
//}
}
//}
}
template <class T>
inline bool IsSwap(T* pBegin , T* pEnd)
{
T *p;
for(p = pBegin ; p < pEnd ; p++)
{
if(*p == *pEnd)
return false;
}
return true;
}
但是上述方法在存在重复字符的情况下则失效。上述代码中方法1和方法2为简单地改进,希望可以解决含重复字符的字符串全排列。但是在上机运行后发现是行不通的。简单分析了下原因,则是因为这两种改进均不能完成整个解空间的搜索,所以会漏掉部分解,也可能有重复解!
所以现在要换一种思路,在查找一定资源的基础上,发现了如下的有效算法,可以很好地实现字符串的全排列,包括重复字符存在的情况。该算法的思想是:
首先对原字符串进行排序,然后顺序地从原字符中逐个地取字符复制到解空间中,如果某字符和其前一个字符相同,则只处理一次。
简单地将就是在解空间的位置上逐个放置不同的字符,直至全部字符复制完毕。
举例来讲,对于abb,在第一个位置上有a,b两种情况,a时,只有b,b顺序。b时,则有a,b;b,a两种顺序。算法结束。代码如下:
#define MAXBUFFERSIZE 100
using namespace std;
void Permutation(char d[],char s[], int i, int l);
void Sort(char s[]);
int count = 0;
void main()
{
char s[MAXBUFFERSIZE];
char d[MAXBUFFERSIZE];
// input source string//
cout<<"Input source string:"<<endl;
gets(s);
// 排序,排列并输出//
Sort(s);
Permutation( d, s, 0, strlen(s));
return;
}
// 运用递归输出各种排列//
void Permutation(char d[],char s[], int i, int n)
{
int j;
char temp;
for(j = 0; j < n; j ++)
{
if ( j>0 && s[j] == s[j - 1] ) //如果当前字符和前一个字符串相同,则跳过该字符//
;
else if ( s[j] != '#' ) //如果标志为不为'#',即当前字符没有被复制//
{
d[i] = s[j]; //把源串的一个字符赋给目的串//
temp = s[j];
s[j] = '#';
if(i == n - 1)
{
d[n] = '\0';
cout<<setw(2)<<++::count<<":"; // 打印出其结果//
cout<<d<<endl;
}
else
Permutation( d, s, i + 1, n); // 递归调用//
s[j] = temp; // 回溯//
}
}
}
// 冒泡排序//
void Sort(char s[])
{
int n = strlen(s);
int i, j;
char temp;
for(i = 0; i < n - 1; i ++)
for(j = i + 1; j < n; j ++)
if(s[i] > s[j])
{
temp = s[i];
s[i] = s[j];
s[j] = temp;
}
}
运行结果如下图所示:
当然,这种算法也存在着两个主要缺点:
1、额外增加了排序算法,耗时增加;
2、复制相当于使用了外部空间,空间使用增加。