您的位置:首页 > 其它

含重复字符的字符串组合算法(深度优先搜索树递归实现)

2012-08-12 21:08 232 查看
今天研究了字符串的组合,和字符串的全排列不同的是,组合只考虑元素的个数而不考虑元素的排列顺序。对于不含重复字符的字符串全排列,笔者搜索到的最简单的算法如下所示,来源http://hi.baidu.com/%C2%AC%B1%C8%D0%A1%BE%AB%C1%E9/blog/item/21363d8912977fc09023d97d.html

void substr(char *str)
{
int i, j,n=strlen(str), m=1<<n, k;
for(i=1; i<m;i++)
{
for(j=0,k=i; k>0; k>>=1, j++)
if(k&0x01) putchar(str[j]);
putchar('n');//此处应为'\n',原代码可能有错误
}
}


即在串中没有相同字符时, 一个最简单的思路,设串长为n,把它和一个n位的二进制数关联起来,这个数从1跑到2^n时就跑遍了所有的字符的组合。

但是对于含重复字符时,上述方法是行不通的。笔者经过思考,对于含重复字符的字符串,可以这样遍历它的所有组合,例如acc这个字符串,这样求其组合,a,ac,acc,c,cc。也就是按照深度优先搜索其所有组合,其对应的搜索树如下图所示:



就是说,每一层节点包含字符串的长度是从1开始递增的,如果存在相同字符,则只取一次,按照深度优先搜索遍历,处理完所有字符时回溯、递归,即可求出所有组合。

为了方便判断回溯去掉的字符是否与待处理字符相同,预先对字符串进行了排序,当然如果不想排序,也可以通过容器将回溯掉的所有元素保存,再遍历是否和待处理字符相同即可。代码如下:

#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <iomanip>
#define MAXBUFFERSIZE 100
using namespace std;

void zuhe(char d[],char s[], int i,int flag,int n);
/*
i :		输出字串的长度
flag :	当前处理字符的位置
n:		原始字符串的长度
*/
void Sort(char s[]);
int  count2 = 0;
char temp=' ';

void main()
{
char s[MAXBUFFERSIZE];
char d[MAXBUFFERSIZE];
// input source string//
cout<<"Input source string:"<<endl;
gets(s);
// 排序,排列并输出//
Sort(s);

::temp=' ';
zuhe( d, s, 0,0,strlen(s));

return;
}
void zuhe(char d[],char s[], int i,int flag,int n)
{
int j;
if (flag<n)
{
for(j=flag ; j < n;j++ )
{
if ( s[j] == ::temp ) //如果当前字符和回溯去掉的字符相同,则跳过该字符//
{
flag++;
continue;
}
else
{
flag++;
d[i] = s[j];				//把源串的一个字符赋给目的串//
cout<<setw(2)<<++::count2<<":";
for (int k=0;k<=i;k++)
cout<<d[k];         // 打印出其结果//
cout<<endl;

zuhe( d, s, i + 1,flag,n);			// 递归调用//
::temp=d[i];
d[i] = ' ';	// 回溯//
}
}
}
}

// 冒泡排序//
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;
}
}

运行结果如下图所示:





内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐