全排列(递归做法)

排列:从n个元素中任取m个元素,并按照一定的顺序进行排列,称为排列;

全排列:当n==m时,称为全排列;

比如:集合{ 1,2,3}的全排列为:

{ 1 2 3}  { 1 3 2 }  { 2 1 3 }  { 2 3 1 }  { 3 2 1 }  { 3 1 2 }

排序思路:(递归)

 (1)n个元素的全排列=(n-1个元素的全排列)+(另一个元素作为前缀);

(2)出口:如果只有一个元素的全排列,则说明已经排完,则输出数组;

(3)不断将每个元素放作第一个元素,然后将这个元素作为前缀,并将其余元素继续全排列,等到出口,出口出去后还需要还原数组;

用图形表示为:

 黑色方框表示:选取每一个元素作为前缀,后面的数据再进行全排列,直到待排序队列只有一个元素,这时这一趟排列结束,打印出。

伪代码分析:

函数:Void Perm(int *arr,int head,int tail);

//参数说明:arr 数组地址,

//head:进行排列的第一个元素下标

//tail:进行排列最后一个元素下标

 

因为Perm(n) = arr[0]Perm(n-1)+arr[1] Perm(n-1)+……+arr[n-1] Perm(n-1)

所以这里用递归的做法,递归结束条件是Perm(1) = arr[x];

伪代码说明:

void Perm(int *arr,int head,int tail)
{
	if(head == tail)//如果相等 说明遍历到最后,没有元素能当前缀,所以这一趟全排列结束
	{
		ShowArray();//打印这一次排列的结果
	}
	else
	{
		For(int j = head ; j <= tail;j++)//j表示的每一个元素一次做前缀
		{
			Swap(arr[head],j); //交换j到最前面 
			Perm(arr,head+1,tail); //全排列后面的所有元素(这里是head+1,而不是head++)
			Swap(arr[head],j); //还需要将之前交换的再换回 否则整个数组顺序全被打乱
		}
	}
}
////全排列后面的所有元素(这里是head+1,而不是head++,head++代表参数++,递归的下一个head和上一个head不相同,所以要head+1计算)

完整代码以及程序运行结果:

void ShowArray(int *arr,int len)
{
	for(int i = 0;i<len;i++)
	{
		cout<<arr[i]<<" ";
	}
	cout<<endl;
}
void Swap(int &a,int &b)
{
	int c= b;
	b= a;
	a = c;
}
void Perm(int *arr,int k,int m)
{
	if(k == m)//打印
	{
		ShowArray(arr,m+1);
	}
	else
	{
		for(int j = k;j<= m;j++)
		{
			Swap(arr[j],arr[k]);//j k 交换
			Perm(arr,k+1,m);
			Swap(arr[j],arr[k]);
		}
	}
}

 4个元素的全排列:

 

### C++ 实现全排列递归算法 以下是基于递归和回溯思想实现的 C++ 示例代码,能够输出给定字符串 `str` 的所有可能全排列: ```cpp #include <iostream> #include <string> using namespace std; // 定义递归函数,用于生成全排列 void permute(string& str, int start, int end) { // 如果起始位置等于结束位置,则表示找到种排列方式 if (start == end) { cout << str << endl; return; } // 遍历当前位置及其后的字符,尝试每种可能性 for (int i = start; i <= end; ++i) { // 交换当前字符与其他字符 swap(str[start], str[i]); // 继续处理剩余部分 permute(str, start + 1, end); // 回溯:恢复原始状态以便进行下次交换 swap(str[start], str[i]); } } int main() { string str = "abc"; // 输入字符串 int n = str.length(); // 字符串长度 permute(str, 0, n - 1); // 调用递归函数生成全排列 return 0; } ``` #### 解析 上述代码通过递归调用实现了字符串的全排列功能。核心逻辑如下: - 使用递归函数 `permute` 来逐步固定每位上的字符,对其余未固定的字符继续求解子问题[^3]。 - 每次递归前会交换两个字符以改变顺序,在完成递归后需再交换回来还原原状(即回溯操作)。这步确保了每次递归结束后可以正确返回至上状态探索其他分支[^1]。 此程序对于输入 `"abc"` 将打印出六个不同的排列组合形式,分别是:"abc", "acb", "bac", "bca", "cab", 及 "cba"[^2]. ### 注意事项 为了防止重复计算或者错误结果,注意以下几点: - **去重**:如果输入存在相同字母的情况,应考虑加入额外机制去除冗余项; - **边界条件检查**:确保传入参数有效性和合法性;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值