全排列实现

#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;

/*
 * use STL next_permutation
 */
void permutation0(int *arr, int p, int q)
{
	do
	{
		copy(arr, arr+q, ostream_iterator<int>(cout, " "));
		cout<<endl;
	}while(next_permutation(arr, arr+q));
}

/*
 * use recursion
 */
void permutation1(int *arr, int p, int q)
{
	if(p == q)
	{
		copy(arr, arr+q, ostream_iterator<int>(cout, " "));
		cout<<endl;
		return;
	}
	for(int i=p; i<q; i++)
	{
		swap(arr[i], arr[p]);
		permutation1(arr, p+1, q);
		swap(arr[i], arr[p]);
	}
}


/*
 * implement next_permutation version 1 in STL
 * 在i+1->n-1中,找到第一个比i大的数,交换,然后将i+1以后的数按从小到大排序,
 * 这样保证了无跳跃情况出现
 */
bool nextPermutation1(int *arr, int n)
{
	int i;
	for(i=n-2; i>=0; i--)
	{
		for(int j=n-1; j>i; j--)
		{
			if(arr[j] > arr[i])
			{
				swap(arr[i], arr[j]);
				sort(arr+i+1, arr+n);
				return true;
			}
		}
	}
	if(0 > i)
	{
		return false;
	}
	return true;
}

/*
 * implement next_permutation version 2 in STL
 * 分析发现,我们逆向寻找第一个i满足arr[i]<arr[i+1],此时有arr[i]<arr[i+1]>arr[i+2]>arr[i+3]>...
 *	则arr[i]是需要被交换的元素,而从i+1->n-1是逆序的,无法寻找到下一个排列
 *	此时,可用一次循环寻找i,若未找到,全排列完毕,返回
 * 进一步分析发现,若在arr中逆向找到第一个下标 j 满足arr[i]<arr[j],
 *	则有...>arr[j-1]>arr[j]>arr[i]>arr[j+1]>..., 因此arr从i+1->n-1在交换前后都是逆序的
 * 此时只需逆转i+1->n-1部分,而无须进行排序,进而保证交换后无跳跃情况
 */
bool nextPermutation2(int *arr, int n)
{
	int i;
	for(i=n-2; i>=0; i--)
	{
		if(arr[i] < arr[i+1])
		{
			break;
		}
	}
	if(0 > i)
	{
		return false;
	}
	for(int j=n-1; j>i; j--)
	{
		if(arr[j] > arr[i])
		{
			swap(arr[i], arr[j]);
			reverse(arr+i+1, arr+n);
			return true;
		}
	}
	return true;
}

/*
 * implement permutation by ourselves
 */
void permutation2(int *arr, int p, int q)
{
	do
	{
		copy(arr, arr+q, ostream_iterator<int>(cout, " "));
		cout<<endl;
	}while(nextPermutation2(arr, q));
}

int main()
{
	int a[4] = {1,2,3,4};
	permutation2(a, 0, 4);
	return 0;
}

你可能感兴趣的:(全排列实现)