下一个排列问题 C++代码

/*
此程序解决生成某一个排列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;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值