其实字典全排序并没有想象中的那么难,基本思想方法是:复杂问题分步解决。
此处体现为:1要输出整个全排序,只需先实现“给出一串字符之后判断它的后面是否还可输出字符串,如果有的话,如何给出它的下一个字符串”的问题。
2、用递归把问题步骤1的解决过程包裹起来。
算法:
设P是1~n的一个全排列:p=p1p2......pn=p1p2......pj-1pjpj+1......pk-1pkpk+1......pn
1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即 j=max{i|pi<pi+1} 2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk,即 k=max{i|pi>pj}(右边的数从右至左是递增的,因此k是所有大于pj的数字中序号最大者) 3)对换pi,pk 4)再将pj+1......pk-1pkpk+1......pn倒转得到排列p'=p1p2.....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个排列。步骤1的实现为
#include<iostream>//ere
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
char a[55];
while(cin>>a&&a[0]!='#')
{
int len=strlen(a);
int p=1;//用于标记,来判断一个字符串是否有后续的字符串
for(int i=0;i<len-1;i++)
{
if(a[i]<a[i+1])
{
p=0;
break;
}
}
if(p==1) cout<<"No Successor"<<endl;//无后续的情况
else
{//确定哪一位要换
int t;//第t位要换
for(int i=len;i>=1;i--)
{
if(a[i]>a[i-1])
{
t=i-1;
break;
}
}
sort(a+t+1,a+len);
for(int i=t+1;i<len;i++)
{
if(a[t]<a[i])//若无此步,输入ere的时候输出它的下一个字符串将是eer
{
swap(a[t],a[i]);
break;
}
}
for(int i=0;i<len;i++) cout<<a[i];
cout<<endl;
}
}
}
步骤2实现:包装
#include<iostream>//ere
#include<cstring>
#include<algorithm>
using namespace std;
char a[55];
void f(char a[],int len)
{
int p=1;//用于标记
for(int i=0;i<len-1;i++)
{
if(a[i]<a[i+1])
{
p=0;
break;
}
}
if(p==1) return;//cout<<"No Successor"<<endl;//判断无后续的情况
else
{//确定哪一位要换
int t;//第T位要换
for(int i=len;i>=1;i--)
{
if(a[i]>a[i-1])
{
t=i-1;
break;
}
}
sort(a+t+1,a+len);
for(int i=t+1;i<len;i++)
{
if(a[t]<a[i])
{
swap(a[t],a[i]);//ere的情况
break;
}
}
for(int i=0;i<len;i++) cout<<a[i];
cout<<endl;
f(a,len);
}
}
int main()
{
while(cin>>a&&a[0]!='#')
{
int len=strlen(a);
sort(a,a+len);
for(int i=0;i<len;i++) cout<<a[i];
cout<<endl;
f(a,len);
}
}