您的位置:首页 > 其它

含重复字符的字符串全排列算法(思路+分析)

2012-08-12 13:07 288 查看
从昨天到现在一直在回顾字符串的全排列算法,之前简单地复习了不含重复字符的字符串全排列,所以这次想彻底解决该算法。关于不含重复字符的字符串全排列比较简单,直接用递归思路解决即可,简单代码如下:

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
= '\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、复制相当于使用了外部空间,空间使用增加。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐