字典序算法如下:
设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=min{pk|pk>pj,k>i}
3)对换pi,pk
4)再将pj+1......pk-1pkpk+1pn倒转得到排列p’’=p1p2.....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个下一个排列。
例如839647521是数字1~9的一个排列。从它生成下一个排列的步骤如下:
自右至左找出排列中第一个比右边数字小的数字4 839647521
在该数字后的数字中找出比4大的数中最小的一个5 839647521
将5与4交换 839657421
将7421倒转 839651247
所以839647521的下一个排列是839651247。
我把自己写的源代码贴上来供大家学习:
#include<stdio.h>
#include<string.h>
int fact(int n);
void sort(char s[]);
void main()
{
int n,i;
char s[1000];
scanf("%d",&n);
for(i=0;i<n;i++)
s[i]=i+1+‘0‘;
s[i]=‘\0‘;
for(i=0;i<fact(n);i++)
{
printf("%s\n",s);
sort(s);//生成下一个排列数
}
}
int fact(int n)
{
int fact=1,i;
for(i=2;i<=n;i++)
fact=fact*i;
return fact;
}
void sort(char s[])
{
int len,i,j,tem,min;
len=strlen(s);
for(i=len-1;i>0;i--)
if(s[i-1]<s[i])
break;
min=i;
for(j=i+1;j<len;j++)
if(s[j]>s[i-1]&&s[j]<s[min])
min=j;
tem=s[i-1];
s[i-1]=s[min];
s[min]=tem;
for(j=i;j<(len+i)/2;j++)
{
tem=s[j];
s[j]=s[len-1+i-j];
s[len-1+i-j]=tem;
}
}
运行结果: