现在的位置: 首页 > 综合 > 正文

排列算法实现 交换两个元素组合算法实现

2013年10月28日 ⁄ 综合 ⁄ 共 4012字 ⁄ 字号 评论关闭
文章目录

排列算法

从集合S(n)中,任取k(k≤n)个元素,按照一定的顺序(有序性)排成一列,叫做集合S的一个k-排列。
从集合S(n)中,取出的k-排列的总个数,叫做集合S的k-排列数。

排列符号:

这里介绍3种排列形式:
1.全排列。
2.不重复全排列。
3.选择排列。

1.全排列

从集合S(n)中,取出的所有的n-排列。规模数为nPn = n!。

1)交换_递归

代码中调用的函数Swap,功能为:交换两个元素

//交换 递归
//p:表示递归到第p层
typedef char ElemType;
void _full_prem_swap_recursion(ElemType *A, int N, int p)
{
	static int count = 1;
	if (p == N)
	{
		cout<<"["<<count<<"\t] = ";
		for (int i = 0; i < N; ++i)
		{
			cout<<A[i]<<" ";
		}
		cout<<endl;
		count++;
		return;
	}

	for (int i = p; i < N; ++i)
	{
		Swap(A[i], A[p]);//交换
		_full_prem_swap_recursion(A, N, p + 1);
		Swap(A[i], A[p]);//恢复
	}
}
void full_prem_swap_recursion(ElemType *A, int N)
{
	_full_prem_swap_recursion(A, N, 0);
}

输入:A B C

输出:

2)选择_递归
typedef char ElemType;

typedef struct stElemNode
{
	ElemType value;
	unsigned char num;
} ElemTypeEx;

template< class T > void SafeDelete( T*& pVal )
{
	delete pVal;
	pVal = NULL;
}

template< class T > void SafeDeleteArray( T*& pVal )
{
	delete[] pVal;
	pVal = NULL;
}

//全排列
//选择递归
void _full_prem_select_recursion(ElemTypeEx *A, int N, ElemType *choosed, int p)
{
	static int count = 1;
	if (p == N)
	{
		cout<<"["<<count<<"\t] = ";
		for (int i = 0; i < N; ++i)
		{
			cout<<choosed[i]<<" ";
		}
		cout<<endl;
		count++;
		return;
	}

	for (int i = 0; i < N; ++i)
	{
		if (A[i].num > 0)
		{
			--A[i].num; //可用次数减1
			choosed[p] = A[i].value;
			_full_prem_select_recursion(A, N, choosed, p+1); 
			++A[i].num; //可用次数恢复
		}
	}
}

void full_prem_select_recursion(const ElemType *A, int N)
{
	ElemTypeEx *A_Ex = new ElemTypeEx[N];

	for (int i = 0; i < N; ++i)
	{
		A_Ex[i].value = A[i];
		A_Ex[i].num = 1;
	}

	ElemType *choosed = new ElemType[N];

	_full_prem_select_recursion(A_Ex, N, choosed, 0);

	SafeDeleteArray(A_Ex);
	SafeDeleteArray(choosed);
	return;
}

输入:A B C

输出:

 

2.不重复全排列

集合S(m)中有相异元素n(1 <= n <= m)个,生成的排列中会有重复的,需要剔除。规模数为:

1)交换_递归
//不重复全排列
//交换 递归
//p:表示递归到第p层
typedef char ElemType;
void _unrepeat_prem_swap_recursion(ElemType *A, int N, int p)
{
	static int count = 1;
	if (p == N)
	{
		cout<<"["<<count<<"\t] = ";
		for (int i = 0; i < N; ++i)
		{
			cout<<A[i]<<" ";
		}
		cout<<endl;
		count++;
		return;
	}

	for (int i = p; i < N; ++i)
	{
		//减枝
		//如果A[i]与A[p...i-1]的任一元素相同,则表示这个待生成的序列是重复的,需要跳过
		bool find = false;
		for (int j = p; j < i; ++j)
		{
			if (A[i] == A[j])
			{
				find = true;
				break;
			}
		}
		if (find)
		{
			continue;
		}

		Swap(A[i], A[p]);//交换
		_unrepeat_prem_swap_recursion(A, N, p + 1);
		Swap(A[i], A[p]);//恢复
	}
}

void unrepeat_prem_swap_recursion(ElemType *A, int N)
{
	_unrepeat_prem_swap_recursion(A, N, 0);
}

输入:A A C D

输出:

2)选择_递归
//不重复全排列
//选择 递归
//p:表示递归到第p层
void _unrepeat_prem_select_recursion(ElemTypeEx *A, int N, int M, ElemType *choosed, int p)
{
	static int count = 1;
	if (p == M)
	{
		cout<<"["<<count<<"\t] = ";
		for (int i = 0; i < M; ++i)
		{
		cout<<choosed[i]<<" ";
		}
		cout<<endl;
		count++;
		return;
	}

	for (int i = 0; i < N; ++i)
	{
		if (A[i].num > 0)
		{
			--A[i].num; //可用次数减1
			choosed[p] = A[i].value;
			_unrepeat_prem_select_recursion(A, N, M, choosed, p+1); 
			++A[i].num; //可用次数恢复
		}
	}
}
//不重复全排列
void unrepeat_prem_select_recursion(const ElemType *A, int N)
{
	ElemTypeEx *A_Ex = new ElemTypeEx[Count_unrepeat(A,N)];
	int M = 0;
	Compress(A, N, A_Ex, M);

	ElemType *choosed = new ElemType[N];

	_unrepeat_prem_select_recursion(A_Ex, M, N, choosed, 0);

	SafeDeleteArray(A_Ex);
	SafeDeleteArray(choosed);
}

输入:A A C D

输出:

 

3.选择排列

从集合S(n)中,取出的所有的k-排列。规模数为nPk。

1)交换_递归
//选择排列 P(N, M)
//交换递归
//p:表示递归到第p层
typedef char ElemType;
void _select_prem_swap_recursion(ElemType *A, int N, int M, int p)
{
	static int count = 1;
	if (p == M)
	{
		cout<<"["<<count<<"\t] = ";
		for (int i = 0; i < M; ++i)
		{
			cout<<A[i]<<" ";
		} 
		cout<<endl;
		count++;
		return;
	}

	for (int i = p; i < N; ++i)
	{
		Swap(A[i], A[p]);//交换
		_select_prem_swap_recursion(A, N, M, p + 1);
		Swap(A[i], A[p]);//恢复
	}
}
void select_prem_swap_recursion(ElemType *A, int N, int M)
{
	_select_prem_swap_recursion(A, N, M, 0);
}

输入:A B C k = 2

输出:

2)选择_递归
//选择排列
//选择递归
//p:表示递归到第p层
typedef char ElemType;

typedef struct stElemNode
{
	ElemType value;
	unsigned char num;
} ElemTypeEx;

void _select_prem_select_recursion(ElemTypeEx *A, int N, int M, ElemType *choosed, int p)
{
	static int count = 1;
	if (p == M)
	{
		cout<<"["<<count<<"\t] = ";
		for (int i = 0; i < M; ++i)
		{
			cout<<choosed[i]<<" ";
		}
		cout<<endl;
		count++;
		return;
	}

	for (int i = 0; i < N; ++i)
	{
		if (A[i].num > 0)
		{
			--A[i].num; //可用次数减1
			choosed[p] = A[i].value;
			_select_prem_select_recursion(A, N, M, choosed, p+1); 
			++A[i].num; //可用次数恢复
		}
	}
}
void select_prem_select_recursion(const ElemType *A, int N, int M)
{
	ElemTypeEx *A_Ex = new ElemTypeEx[N];

	for (int i = 0; i < N; ++i)
	{
		A_Ex[i].value = A[i];
		A_Ex[i].num = 1;
	}

	ElemType *choosed = new ElemType[N];

	_select_prem_select_recursion(A_Ex, N, M, choosed, 0);

	SafeDeleteArray(A_Ex);
	SafeDeleteArray(choosed);
	return;
}

输入:A B C k = 2

输出:

 

常见的排列有以上三种,若有其他形式的排列,可以通过上面的三种组合出来。

如想了解常见的组合算法的实现,可以参考组合算法实现

抱歉!评论已关闭.