枚 举 排 列

版权声明:个人学习笔记记录 https://blog.csdn.net/Ratina/article/details/84062167

照着《入门经典》理解整理了一下。

① 以字典序生成1~n的排列 (递归枚举)

运用一层层的递归,形成一个解答树。

#include<cstdio>
using namespace std;
void print_permutation_1(int n,int *ar,int cur)
{                   //ar存储排列,cur表示当前ar中排列到第几个
	if(cur==n)      //当cur==n,即已排列到末尾,则打印该排列
	{
		for(int i=0; i<n; i++)
			printf("%d ",ar[i]);
		printf("\n");
	}
	else
	{
		for(int i=1; i<=n; i++)        //从1~n选择元素放入当前的ar[cur]
		{
			bool ok=true;
			for(int j=0; j<cur; j++ )  //确保选择的i还不在排列中
			{
				if(ar[j]==i)
					ok=false;
			}
			if(ok)
			{
				ar[cur]=i;
				print_permutation_1(n,ar,cur+1);   //递归,cur+1
			}
		}
	}
}

② 以字典序生成可重集的排列
给定一个数组P,按字典序输出所有排列,数组P中会有重复元素。

要先让数组P从小到大排好序,答案不能有重复的排列,也不能缺少元素。

#include<cstdio>
using namespace std;
void print_permutation_2(int n,int *P, int *ar,int cur)
{
	if(cur==n)
	{
		for(int i=0; i<n; i++)
			printf("%d ",ar[i]);
		printf("\n");
	}
	else
	{
		for(int i=0; i<n; i++)      //从P[0]到P[n-1]选择元素放入当前ar[cur]
		{
			//因为之后要通过比较P和ar中该元素的数量来判断是否选择该元素,
			//所以用以下的if来略过相同元素,以此防止出现相同排列。
			if(i==0||(i!=0&&P[i]!=P[i-1])) 
			{
				int c1=0,c2=0;             //c1记录ar中该元素的数量
				for(int j=0; j<cur; j++ )  //c2记录P中该元素的数量
				{
					if(ar[j]==P[i])
						c1++;
				}
				for(int j=0; j<n; j++)
				{
					if(P[j]==P[i])
						c2++;
				}
				if(c1<c2) 
				{
					ar[cur]=P[i];
					print_permutation_2(n,P,ar,cur+1);   //递归,cur+1
				}
			}
		}
	}
}

③使用C++ STL中的全排列函数next_permutation

对于next_permutation函数,其函数原型为:

 #include <algorithm>

 bool next_permutation(iterator start,iterator end)

若当前序列不存在下一个排列时,函数返回false,否则返回true

给next_permutation()函数提供一个原排列,就可以得到该排列的下一个排列(字典序)并返回true,到了该排列字典序的最后一个排列则返回false。

next_permutation()适用于可重集

#include<cstdio>
#include<algorithm> 
using namespace std;
int main()
{
	int n,P[10];
	scanf("%d",&n);
	for(int i=0;i<n;i++)
		scanf("%d",P+i);
	sort(P,P+n);        //生成最小的排列
	do{
		for(int i=0;i<n;i++)
			printf("%d ",P[i]);
		printf("\n");
	}while(next_permutation(P,P+n));  //从 首地址 到 末地址+1
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Ratina/article/details/84062167