全排列递归算法详细解释(非字典序)

字典序输出请点击 字典序输出全排列

中心思想

设R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R-{ri}.
Perm(X)表示在全排列Perm(X)的每一个排列前加上前缀ri得到的排列。

  • 当n=1时,Perm(R)=(r),其中r是集合R中唯一的元素;
  • 当n>1时,Perm®可由(r1)+Perm(R1),(r2)+Perm(R2),…,(rn)+Perm(Rn)构成。

那么具体程序要怎么实现呢?我们来个实际的例子,假设有一数列1,2,3,4,那么1,2,3,4的全排列:perm({1,2,3,4})=1perm({2,3,4})+2perm({1,3,4})+3perm({1,2,4})+4perm(1,2,3)
那么我们只要将每个数,与第一个数交换不就可以得到下一个序列了吗?
比如{1,2,3,4}第一个与第二个数交换,那么不就得到2 {1,3,4}了

接下来我们用一个实际的例子说明该程序是怎样运行的

具体算法流程:

  • 数列:{1,2,3} 第一个与第一个交换,可以得到1 {2,3} 将序列{2,3}放进perm函数递归,然后
    ——递归{2,3}
    数列{2,3}第一个与第一个交换, 得到2{3} ,输出1,2,3 (此时low=high,因为序列{3}只有一位数,因此输出列表list)
    数列{2,3}第一个与第一个交换回来,结果仍然是{2,3}
    数列{2,3}第一个与第二个交换, 得到3{2},输出1,3,2
    {3,2}又第一个与第二个交换回来,变回{2,3}
    —–{2,3}递归完毕序列恢复原状{1,2,3}

  • 数列:{1,2,3} 第一个与第二个交换,可以得到2,{1,3}
    ——递归{1,3}
    数列{1,3}第一个与第一个交换,得到1{3} ,输出2,1,3
    数列{1,3}第一个与第一个交换回来,结果仍然是{1,3}
    数列{1,3}第一个与第二个交换,得到3{1},输出2,3,1
    {3,1}又第一个与第二个交换回来,变回{1,3}
    —–{1,3}递归完毕
    序列{2,1,3}第一个与第二个交换,序列恢复原状{1,2,3}

  • 数列:{1,2,3} 第一个与第三个交换,可以得到3,{1,2}
    ——递归{1,2}
    数列{1,2}第一个与第一个交换,得到1{2} ,输出3,1,2
    数列{1,2}第一个与第一个交换回来,结果仍然是{1,2}
    数列{1,2}第一个与第二个交换,得到2{1},输出3,2,1
    {2,1}又第一个与第二个交换回来,变回{1,2}
    —–{1,2}递归完毕
    序列{3,1,2}第一个与第二个交换,序列恢复原状{1,2,3}

算法可以简单地写作
perm({1,2,3})=1perm({2,3})+2perm({1,3})+3perm({1,2})
perm({2,3})=2perm({3})+3perm({2})
perm({1,3})=1perm({3})+3perm({1})
perm({1,2})=1perm({2})+2perm({1})

#include<iostream>
using namespace std;
//交换
void swap(int &a , int &b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
 } 
 //全排列递归算法
void Perm(int list[] , int k ,int m) 
{
	//list 数组存放排列的数,K表示层 代表第几个数,m表示数组的长度
	if(k==m)
	{
		//K==m 表示到达最后一个数,不能再交换,最终的排列的数需要输出;
		for(int i=0 ;i<=m ;i++)
		 cout<<list[i];
		 cout<<endl; 
	 } 
	 else{
	 	for(int i=k;i<=m;i++)
	 	{
	 		swap(list[i],list[k]);
	 		Perm(list,k+1,m);
	 		swap(list[i] , list[k]);
		 }
	 }
	 
}
int main(void)
{
   int a[]={1,2,3};
   int m=2;
   Perm(a,0,2);
	/*
  123
  132
  213
  231
  321
  312
*/
 } 

原文链接:https://blog.csdn.net/a358463121/article/details/45543879

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值