【C++】 ——全排列算法

关于全排列算法,分为两种:可重复的全排列和不包含重复的元素的全排列

一、含重复元素的全排列

算法思路:
(1)n个元素的全排列=(n-1个元素的全排列)+(另一个元素作为前缀);
(2)出口:如果只有一个元素的全排列,则说明已经排完
(3)不断将每个元素放作第一个元素,然后将这个元素作为前缀,并将其余元素继续全排列,等待出口,出口出去后还需要还原数组

#include <iostream>
#include <stdlib.h>
#include <vector>
using namespace std;

void swap(vector<int>&a, int i, int j)
{
	int temp;
	temp = a[j];
	a[j] = a[i];
	a[i] = temp;
}

void prem(vector<int>&a, int start, int end, vector<vector<int>>&ret)
{
	if (start == end)
	{
		vector<int>::iterator iter;
		for (iter = a.begin(); iter < a.end(); iter++)
		{
			cout << (*iter) << "   ";
		}
		cout << endl;

		ret.push_back(a);
		return;
	}
	else
	{
		for (int i = start; i <= end; i++)
		{
 			swap(a, start, i);
			prem(a, start + 1, end, ret);  //每次选择子后一个元素为开始第一个元素
			swap(a, i, start);
		}
	}
}

int main()
{
	vector<int> v = { 1,2,3,4};
	vector<vector<int>> ret;
	int start = 0, end = v.size()-1;
	prem(v, start, end, ret);
	vector<vector<int>>::iterator iter;
	cout << endl;
	system("pause");
	return 0;
}

二、不包含重复元素

因为排序是前缀加上后缀,所以要保证前缀每次都不一样才可以,也就是说交换后不能重复,所以在交换前要进行排查
只要从start开始到end(不包括end包括start)中间的元素与end元素相等,那么前缀就有可能相同,所以要去掉

去重的规则:去重的的全排列就是与当前元素 i 交换的元素 j 不能与 i~j 之间的元素相同,这样才可以保证前缀不一样。因此我们在上一题的基础上再完善下就可以

#include <iostream>
#include <stdlib.h>
#include <vector> 
using namespace std;

bool IsSwap(vector<int>& a, int start, int end)
{
	for (int i = start; i < end; i++)
		if (a[i] == a[end])
			return false;
	return true;
}
void swap(vector<int>&a, int i, int j)
{
	int temp;
	temp = a[j];
	a[j] = a[i];
	a[i] = temp;
}

void prem(vector<int>&a, int start, int end, vector<vector<int>>&ret)
{
	if (start == end)
	{
		vector<int>::iterator iter;
		for (iter = a.begin(); iter < a.end(); iter++)
		{
			cout << (*iter) << "   ";
		}
		cout << endl;

		ret.push_back(a);
		return;
	}
	else
	{
		for (int i = start; i <= end; i++)
		{
			if (IsSwap(a, start, i))
			{
				swap(a, start, i);
				prem(a, start + 1, end, ret);  //每次选择子后一个元素为开始第一个元素
				swap(a, i, start);
			}
 			
		}
	}
}

int main()
{
	vector<int> v = { 2,2,3,4};
	vector<vector<int>> ret;
	int start = 0, end = v.size()-1;
	prem(v, start, end, ret);
	vector<vector<int>>::iterator iter;
	cout << endl;
	system("pause");
	return 0;
}
原创文章 78 获赞 21 访问量 3540

猜你喜欢

转载自blog.csdn.net/Vicky_Cr/article/details/105555341