n的全排列分治递归求解

设计一个递归算法生成n个元素{r1,r2,…,rn}的全排列。 设R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R-{ri}。 集合X中元素的全排列记为perm(X)。 (ri)perm(X)表示在全排列perm(X)的每一个排列前加上前缀得到的排列。

R的全排列可归纳定义如下: 当n=1时,perm( R) = ( r ),其中r是集合R中唯一的元素; 当n>1时,perm( R)由(r1)perm(R1),(r2)perm(R2),…,(rn)perm(Rn)构成。

有n个元素,把它们编号为1,2…n,用一个数组A 来存放所生成的排列,然后输出它们。假定开始时n个元素以依次存放在数组A中,为了生成这n个元素的所有排列,可以采取下面的步骤:
(1)第一个元素为1,即排列的第一个元素为1,生成后面n-1个元素的排列。
在这里插入图片描述
在上面的第一步 ,为生成后面n-1个元素的排列,继续采取下面的步骤:
(1)第二个元素为2,即排列的第二个元素为2,生成后面n-2个元素的排列。
在这里插入图片描述
(2)第二个元素和第三个元素互换,使排列的第二个元素为3,生成后面n-2个元素的排列。
在这里插入图片描述
(3)如此继续,最后第二个元素和第n个元素互换,使排列的第二个元素为n,生成后面n-2个元素的排列。

在这里插入图片描述
这种步骤一直继续,当排列的前n-2个元素已确定后,为生成后面2个元素的排列,可以:
(1)第n-1个元素为n-1,即排列的第n-1个元素为n-1,生成后面1个元素的排列,此时n个元素已构成一个排列。
(2)第n-1个元素和第n个元素互换,使排列的第n-1个元素为n,生成后面1个元素的排列,此时n个元素已构成一个排列。
令排列算法perm(A,k,n)表示生成数组后面 个元素的排列。通过上面的分析有:
(1)基础步:k=1,只有一个元素,已构成一个排列。
(2)归纳步:对任意的k,1<k<=n完成perm(A,k-1,n),逐一对第n-k元素与第n-k~n元素进行互换,每互换一次,就执行一次perm(A,k -1,n)操作,产生一个排列。

算法可以如下描述:

void perm(int A[],int k,int n)
{
    if(k==1)
        PrintA(n);
    else
    {
        for(int i=n-k+1;i<=n;i++)//初始值k=n,i=1,交换A[1]和A[1],执行perm(A,n-1,n);
                                //i=2,交换A[2]和A[1],执行perm(A,n-1,n);
                                //i=3,交换A[3]和A[1],执行perm(A,n-1,n);
        {
            swap(A[i],A[n-k+1]);
            perm(A,k-1,n);
            swap(A[i],A[n-k+1]);
        }
    }
}

输入

输入只有一行,输入整数n
样例输入:

3

输出

输出有n!行,输出1-n的n!种排列,每个数字中间有一个空格

样例输出:

1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
3 1 2

完整代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int A[101];
void PrintA(int n)
{
    for(int i=1;i<=n;i++)
        cout<<A[i]<<" ";
    cout<<endl;
}
//PrintA时间复杂度:O(n)
void perm(int A[],int k,int n)
{
    if(k==1)
        PrintA(n);
    else
    {
        for(int i=n-k+1;i<=n;i++)//初始值k=n,i=1,交换A[1]和A[1],执行perm(A,n-1,n);
                                //i=2,交换A[2]和A[1],执行perm(A,n-1,n);
                                //i=3,交换A[3]和A[1],执行perm(A,n-1,n);
        {
            swap(A[i],A[n-k+1]);
            perm(A,k-1,n);
            swap(A[i],A[n-k+1]);
        }
    }
}
//perm时间复杂度:O(n!)*O(n)
int main()//1 2 3
{
    int n;
    cin>>n;
    //赋初值
    for(int i=1;i<=n;i++)
        A[i]=i;
    perm(A,n,n);
    return 0;
}

在这里插入图片描述

运行结果

在这里插入图片描述

  • 7
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值