给定字符串的所有排列

对于这类问题之前想到的解决方案都是 借助标志数组和递归的方式找出所有排列情况:

代码如下:


#include<stdio.h>
#include<string.h>


// 定义数组长度
#define LEN 20

//原数据数组
char data[LEN];

//组合得到的目标数据数组
char desData[LEN];

//标志数组用于记录哪些字符已经使用,避免重复使用同一字符
unsigned char tag[LEN];

//保存字符串长度
unsigned int len;


void PrintAllList(unsigned int index);


int main()
{
while(true)
{
scanf("%s",data);
len=strlen(data);
memset(tag,0,sizeof(tag));
PrintAllList(0);
}
}


void PrintAllList(unsigned int index)
{
if(len<=0)
return;
for(int i=0;i<len;i++)
{
if(!tag[i])
{
if(index==len-1)
{
desData[index]=data[i];
for(int j=0;j<len;j++)
{
printf("%c",desData[j]);
}
printf("\n");
return;
}
else
{
desData[index]=data[i];
tag[i]=1;
PrintAllList(index+1);
tag[i]=0;
}
}
}
}


注意:之前在这里出了一个错误,我想的是找到一个字符就输出一个,而不是保存在字符数组中同一输出;这样一来会有一个问题,例如:对于 字符串 abc,第一个取a时,第二三个字符的组合有 bc cb,但是由于第一个字符只会输出一次,所以就只能输出 abc bc这样的字符组合了。


今天看到一种比较好的解法,无论是从时间上还是空间上都极大的优化了该算法:

#include<stdio.h>


#define LEN 20


char*resPtr;


void PrintAllStrList(char*begin);
void ExchangeData(char*dataOne,char*dataTwo);


int main()
{
while(true)
{
char data[LEN];
scanf("%s",&data);
resPtr=data;
PrintAllStrList(data);
}
}


void PrintAllStrList(char*begin)
{
if(resPtr==NULL || begin==NULL)
return;
if('\0'==*begin)
{
printf("%s\n",resPtr);
return;
}
for(char*pCh=begin;*pCh!='\0';pCh++)
{
ExchangeData(pCh,begin);
PrintAllStrList(begin+1); 
ExchangeData(pCh,begin);
}
}


void ExchangeData(char*dataOne,char*dataTwo)
{
char temp=*dataOne;
*dataOne=*dataTwo;
*dataTwo=temp;
}


但是该算法也存在一个缺陷,就是输出的字符串序列不是有序排列的。 因为他的主要思路是第一个字符和后面的每一个进行交换,例如 abc 如果a和c交换的时候 第一个字符取c,第二个字符的取值情况就变为 先取b 再取a了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值