n个元素共有n!个不同的排列。将这n!个元素按照字典序排列,可以从0编号,直至n!-1。例如,当n=3时,6个不同排列的字典序值为:
0 1 2 3 4 5
123 132 213 231 312 321
编程任务:
给定n以及n个元素的一个排列,计算出这个排列的字典序值;给定一个字典序值,计算出该排列;以及按字典序排列的下一个排列。
#include<stdio.h>
#include<string.h>
int f(int n)
{
if(n==1)
return 1;
return n*f(n-1);
}
//递归,n的阶乘
void move(int t,int a[],int length)
{
for(int i=t+1;i<length;i++)
if(a[i]>a[t])
a[i]--;
}//减去a[i]之前比a[i]小的数
void f1(int n,int a[]){
int i,j,k;
int min=10;
for(i=n-2;i>=0;i--){
if(a[i]<a[i+1]){
j=i; //记录开始减小的数的下标5
break;
}
}
for(int t=j+1;t<n;t++)
if(a[t]<min){
min=a[t];
k=t;
}//k记录倒数第二小的下标 7
a[k]=a[j];
a[j]=min;
int t;
for(i=j+1;i<n-1;i++)
for( t=i; t<n-1; t++)
{
if(a[t] > a[t+1])
{
int temp = a[t];
a[t] = a[t+1];
a[t+1]=temp;
}
}
for(i=0;i<n;i++){
printf("%3d",a[i]) ;
}
}
int main()
{
int n=0;
printf("输入n的值:\n");
scanf("%d",&n);
int a[8];
printf("输入字典序(以空格间隔):\n");
int i,j,k,t;
int count=0;
for(i=0;i<n;i++)
scanf("%d",&a[i]);
printf("该字典序的下一序列为:\n");
f1(n,a);
printf("\n");
for(i=0,k=n-1;i<n;i++,k--)
{
if(k==0)
{
printf("字典序为:%d\n",count-1);
}
else
{
count+=(a[i]-1)*f(k);
move(i,a,n-1);
}
}
return 0;
}