/*
此程序解决生成某一个排列p的下一个排列,并计算排列p的字典序值。
从文件中输入数据,把结果输出到output.txt中.
输入样例:input.txt
8
2 6 4 5 8 1 7 3
输出样例:output.txt
8227
2 6 4 5 8 3 1 7
************************************************************************
分析:
设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)对换pj,pk
4)再将pj+1......pk-1pjpk+1pn反转,这就是排列p的下一个下一个排列。
*************************************************************************
*/
#include<stdio.h>
#include<stdlib.h>
int N ;
int a[100],b[100] ;
int Count=0 ;
void swap(int *a, int *b) // 交换两个变量的值
{
int temp ;
temp = *a;
*a = *b ;
*b = temp ;
}
void Reverse(int L,int R) //将A序列中[L,R]区间的数交换位置
{
while (L<R)
{
swap(&a[L],&a[R]);
++L;
--R;
}
}
bool Next_Arrangement() //求下一个排列
{
int j = N-1 ;
while ( (j>0) && (a[j]>a[j+1]) ) j--;
if ( j==0 ) return false;
int k = j+1 ;
while ( ( k<=N ) && ( a[k]>a[j] ) ) k++ ;
swap( &a[j] , &a[k-1] );
Reverse( j+1 , N );
return true ;
}
bool Is_Same_Arrangement() //判断两个排列是否相等
{
for (int i=1 ; i<=N ; i++)
if ( a[i]!= b[i] ) return false;
return true ;
}
void input() //从文件读入数据
{
FILE *fp = fopen("input.txt","r");
if (fp)
{
fscanf(fp,"%d",&N);
for (int i=1 ; i<=N ; i++) fscanf(fp,"%d",&b[i]);
}
fclose(fp);
}
void output() //向文件输出数据
{
FILE *fp = fopen("output.txt","w");
if (fp)
{
fprintf(fp,"%d\n",Count);
if ( !Next_Arrangement() )
fprintf(fp,"%s","This is the last arrangement!");
else
for (int i=1 ; i<=N ; i++) fprintf(fp,"%d ",a[i]);
}
fclose(fp);
}
void work() //开始工作
{
for (int i=1 ; i<=N ; i++) a[i] = i;
while ( !Is_Same_Arrangement() )
{
++Count ;
if ( !Next_Arrangement() ) break ;
}
}
int main() //主函数
{
input();
work() ;
output();
return 0;
}
下一个排列问题 C++代码
最新推荐文章于 2022-04-15 10:42:44 发布