全排问题

问题:从不同元素中任取m(m<=n)个元素,按照一定的顺序排列起来 ,叫做从n 个不同元素中取出m个元素的一个排列。 当m = n 是所有的排列情况较全排列。

如 1 , 2 , 3 的全排列如下

1 , 2 ,3

1 ,3 , 2

2 ,1 ,3

2 ,3 ,1

3, 1 ,2

3, 2 ,1

当 n = 1 ; 全排列 就是这个数字;

当 n>1 , 全排列为 {  (1)p1 , (2) p2 ,  (3)p3,(4)p4 }, 其中p1= {2,3,4)的全排列 ,p2 = {1,3,4}的全排列 , p3 = {1,2,4}的全排列 , p4 = {1,2,3}的全排列

而p1 ,  p2 ,  p3  , p4 的是用a1分别于第一个,第二个,第三个,直到第n个元素交换之后得到序列的最后三个元素。

这样求n个元素的全排列变成求n次n-1个元素的全排列问题,规模缩小。

 

代码如下

#include<stdio.h>
void swap(int *p ,int *q)
{
    int t = *p;
    *p = *q;
    *q = t;
}

void perm(int a[],int k, int m)
{
    int i;
    if(k==m)
    {
        for(i = 0;i<=m;i++)
        {
            printf("%d",a[i]);
        }
        printf("\n");
    }
    else
    {
        for(i = k;i<=m;i++)
        {
            swap(&a[k],&a[i]);

 perm(a,k+1,m);

    swap(&a[k],&a[i]);
        }
    }
}
int main()
{
    int i , n , a[10];
    scanf("%d",&n);
    for(i = 0;i<n;i++)
        scanf("%d",&a[i]);
    perm(a,0,n-1);
    return 0;
}

全排列输出时候是无序的

比如 在求第n-1个元素的时候  交换后的元素序列变成 n-1 , 2, 3 ,4 ,5 ,6 ,...........n-3, n-2 , 1 , n

此时序列不是有序的 应该变成 n-1 ,1 , 2 ,3 , 4 ,5 ,6 .........,n-4, n-3 ,n-2 ,n

解决优化之后

#include<stdio.h>
void swap(int *p ,int *q)
{
    int t = *p;
    *p = *q;
    *q = t;
}
void  circular_right(int a[],int left,int right)
{
    int t ,i ;
    if(left>=right)
    return ;
    t  = a[right];
    for(i = right;i>left;i--)
        a[i] = a[i-1];
    a[left] = t;
}
void circular_left(int a[],int left,int right)
{
    int t, i ;
     if(left>=right)
        return ;
     t = a[left];
     for(i = left;i<right;i++)
        a[i] = a[i+1];
     a[right] = t;
}
void perm(int a[],int k, int m)
{
    int i;
    if(k==m)
    {
        for(i = 0;i<=m;i++)
        {
            printf("%d",a[i]);
        }
        printf("\n");
    }
    else
    {
        for(i = k;i<=m;i++)
        {
            swap(&a[k],&a[i]);
            circular_right(a,k+1,i);
            perm(a,k+1,m);
           circular_left(a,k+1,i);
            swap(&a[k],&a[i]);
        }
    }
}
int main()
{
    int i , n , a[10];
    scanf("%d",&n);
    for(i = 0;i<n;i++)
        scanf("%d",&a[i]);
    perm(a,0,n-1);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值