PTA数据结构 习题2.8 输出全排列 (20分)

习题2.8 输出全排列 (20分)

请编写程序输出前n个正整数的全排列(n<10),并通过9个测试用例(即n从1到9)观察n逐步增大时程序的运行时间。

输入格式:

输入给出正整数n(<10)。

输出格式:

输出1到n的全排列。每种排列占一行,数字间无空格。排列的输出顺序为字典序,即序列a​1,a​2,⋯,an排在序列b​1,b2,⋯,bn之前,如果存在k使得a1=b1,⋯,ak=bk并且 ak+1 < bk+1

输入样例:

3

输出样例:

123
132
213
231
312
321

全排列字典序算法

全排列生成算法
所谓字典序,就是将元素按照字典的顺序(a-z,1-9)进行排列。strcmp就是以字典序来比较字符串。

字典序算法步骤

设P是集合
{ 1 , 2 , . . . . . . n − 1 , n } \{1,2,......n-1,n\} {1,2,......n1,n}
的一个全排列:P0P1…Pj-1PjPj+1…Pn

集合必须按照递增顺序排列好

  1. 从下标n开始递减,找出第一个比右边数字小的数字序号i
    P i < P i + 1 P_i<P_{i+1} Pi<Pi+1
  2. 在Pi右边的数字里,找到所有比Pj大的数字中最小的数字Pk,即
    k = min ⁡ { i ∣ P i > P j , i > j } k=\min\{i|P_i>P_j,i>j\} k=min{iPi>Pj,i>j}
  3. 交换Pi,Pj
  4. i右边的序列Pi+1Pi+2…Pn逆置,变为PnPn-1…Pi+1

C++代码如下

#include <iostream>
#include <cstdio>

int
fact( int n );

void
dictSeq( int a[], int n );

void
reverse( int a[], int n, int j );

void
swaq( int &a, int &b );

void
print_array( int a[], int n );

int
main( void )
{
	int *a;
	int n;
	scanf("%d", &n);
	a = new int[n];
	for( int i = 0; i < n; i++ ){
		a[i] = i+1;
	}

	int total = fact(n);	//全排列个数等于n!
	print_array( a, n );	//初始序列算一种排列, 在交换之前单独输出

	for( int i = 1; i < total; i++ ){	//让dictSeq执行total-1次, 输出除初始序列之后的所有可能
		dictSeq( a, n );
	}

	return 0;
}

void
dictSeq( int a[], int n )
{
	int i;
	for( i = n-1; i > 0; i-- ){
		if( a[i-1] < a[i] ){
			i--;
			break;	
		}
	}
	
	int min_j = i + 1;
    int min = a[min_j];
	for( int j = min_j; j < n; j++ ){
		if( a[j] > a[i] && min > a[j] ){
			min = a[j];
			min_j = j;
		}
	}
	swaq( a[min_j], a[i] );
	reverse( a, n, i );
	print_array( a, n );
}

void
reverse( int a[], int n, int i )
{
	int left = i + 1, right = n - 1;
	while( left < right ){
		swaq( a[left++], a[right--]);
	}
}

int
fact( int n )
{
	int fact = 1;
	do{
		fact *= n--;
	}while( n > 0 );
	
	return fact;
}

void
swaq( int &a, int &b )
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}

void
print_array( int a[], int n )
{
	for( int i = 0; i < n; i++ ){
		printf("%d", a[i]);
	}
	printf("\n");
}
posted @ 2020-07-31 19:53  LanceHansen  阅读(282)  评论(0编辑  收藏  举报