28+打印并统计字符串的全排列和组合

title:
一、输入一个字符串,打印出字符串中字符的所有排列
二、打印出字符串中字符的所有组合(如ab和ba是两种排列但是只能算一种组合)


thought:
一:
1、将一个字符串分为两部分:第一部分为第一个字符,之后的子串属于第二部分;
2、将第一个字符依次与后面的字符交换;
3、每交换一次,对新串的第二部分子串进行递归的1、2操作;
4、操作完之后,要把交换的两个字符恢复原位:这样做是为了避免出现重复的排序;
5、到达字符串的最末位截止。


二:n是字符串的长度,m是从字符串中选取的字符个数(m=1,2,...n)
1、处理字符*str时,有两种方式:
                         选中此字符,接着处理下一字符*(str+1),然后m变成m-1;
不选此字符,接着处理下一字符*(str+1),但是m保持不变(因为没选*str,所以仍然需要从剩余字符中选取m个);
2、对每个m进行上述处理,m取值从1到n,所以需要调用n次步骤1。

注:当n==0 or m== 0时,实现一种组合。

<pre name="code" class="cpp">#include<iostream>
#include<vector>
using namespace std;

static int cnt_permunation = 0;                //统计全排列的个数
static int cnt_combine = 0;                   //统计字符的组合数
void string_permunation(char *str);
void permunation(char *str,char *str_begin);//str始终指向完整字符串的首字符,str_begin指向当前处理的字符串的首字符
void str_Combine(char *str);
void Combine_recurise(char *str,int m,vector<char> &result);



void string_permunation(char *str)
{
	if(NULL == str)
		return;
	permunation(str,str);
}

void permunation(char *str,char *str_begin)   //str_begin指向当前处理的子串
{
	if(*str_begin == '\0')    //第五步:到达字符串的最末位截止,并输出当前排列
	{
		cout << str << endl;
		cnt_permunation++;
	}
	else
	{
		for(char *str_current = str_begin;*str_current !='\0';str_current++)
		{
			char temp_before = *str_begin;
		    *str_begin = *str_current;           
		    *str_current = temp_before;                  //第一、二步:当前子串的首位与后面的字符交换
			permunation(str,str_begin+1);  // 第三步:交换之后,对新串的子串(str_begin+1)进行全排列(递归)
			char temp_after = *str_begin;   
			*str_begin = *str_current;   
		    *str_current = temp_after;       //第四步:递归全排列之后,把之前交换的两个字符恢复原位
			
		}
	}

}

void str_Combine(char *str)
{
	if(NULL == str || *str == '\0')
		return;

	int length = strlen(str);
	for (int i = 0; i < length; i++)
	{
		vector<char> result;
		Combine_recurise(str,i,result);
	}

}

void Combine_recurise(char *str,int m,vector<char> &result)
{
	if(NULL == str || (*str == '\0' && m != 0))
		return ;
	if(m == 0)                                                  //m==0时,完成一种组合
	{
		cnt_combine++;
		for(int i = 0;i < result.size();i++)
			cout << result[i];
		cout<< endl;
		return ;
	}

	result.push_back(*str);                                  //步骤1:选择此字符,m-1
	Combine_recurise(str+1,m-1,result);              
	result.pop_back();                                      //将选择的字符弹出(变成不选此字符的情况)

	Combine_recurise(str+1,m,result);                    //步骤1:不选此字符,m不变
}


int main()
{
	char str[]="abcd";
	cout << str <<"的全排列如下:"<< endl;
	string_permunation(str);
	cout << "共" <<cnt_permunation << "个全排列" << endl;
	cout << str << "的组合如下:" <<endl;
	str_Combine(str);
	cout << "共" <<cnt_combine << "个组合" << endl;

	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值