PTA习题:习题2.8 输出全排列 (20分)——递归

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

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

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

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

输入样例:

3

输出样例:

123
132
213
231
312
321

我只能想到很简单粗暴的方法,把1~9的所有情况逐个列举出来。
这道题采用递归的方法,想法来自陈越姥姥的《数据结构学习与实验指导》。
首先用一个数组存储1~N。每次把1个数字挑出来放到最左边,然后递归地排列剩下的数字;当只剩下1个数字时,就可以输出了。输出后再把那个挑出来的数字换回原位,继续挑下一个数字放到最左边,以此类推,依次将数组内的所有数字均挑一遍。
为了保证字典序输出,每当挑出1个数字放到最左边时,需要将该数字的左边所有数字整体右移。将挑出的数字放回原位时,将所有右移的数字整体左移,恢复原状。

以输入N=3,将数字2挑出放到最左边为例,数字2左侧所有数字(即数字1)整体右移,得到2 1 3。递归排列1 3,依次输出2 1 3和2 3 1,最后将数字2放回原位,右移数字(即数字1)整体左移,恢复1 2 3,再进行下一轮的“挑数字放到最左边”。

C++实现:

#include
using namespace std;
void permutation(int *L, int left, int right);
int main()
{
	int n;
	int i;
	cin >> n;
	int *L = new int[n];
	for (i = 0; i < n; i++) //数组存储1-n
	{
		L[i] = i + 1;
	}
	permutation(L, 0, n - 1);
	return 0;
}
void permutation(int *L, int left, int right) //递归处理从L[left]到L[right]的全排列
{
	int temp;
	int i, j;
	if (left == right) //递归基:如果只剩1个数字,就输出当前的一组排列
	{
		for (i = 0; i <= right; i++)
		{
			cout << L[i];
		}
		cout << endl;
	}
	else
	{
		for (i = left; i <= right; i++) //依次将数组内所有数字挑一遍
		{
			temp = L[i]; //被挑的数字是L[i]
			for (j = i; j > left; j--) //L[i]左边所有数字整体右移
			{
				L[j] = L[j - 1];
			}
			L[left] = temp;
			permutation(L, left + 1, right); //递归排列剩下数字
			for (j = left; j < i; j++) //将所有右移的数字整体左移,恢复原状
			{
				L[j] = L[j + 1];
			}
			L[i] = temp; //将挑出的数字放回原位置
		}
	}
}

你可能感兴趣的:(数据结构,递归,c++)