全排列算法(C语言)

全排列(C语言)

题意:给定1~n n个正整数,写出它们的所有排列顺序。

思路:根据高中的知识,我们知道不重复的条件下结果是n!个排列顺序。运用递归的思想。

背景

一开始我的想法是用一个数组去存放1-n个正整数,然后再构造一个n*n的二维数组去存放每次递归交换之后该输出的全排列结果,但是这样会十分浪费空间。

之后我又在思考能不能在每次输出一个结果以后就将之前的数据清除,只留一行长度为n的数组空间去交换,但是我始终没有想到最后如何在输出后释放空间进行再一轮排列。

最后老师讲解了思路

思路

递归地把这组数规模一个一个地缩小,如1,2,3,4。先把1固定,递归地求2,3,4的全排列,又把2固定,递归地求3,4的全排列……直到只剩一个数,输出这个排列。

当获取递归数组时,从该组数的第一个,依次和每一位swap交换(包括本身),得以产生一个新递归数组(如1,2,3,4,先是1和1交换,产生新的2,3,4)

当1和1交换产生的所有递归完成之后,实际上已经完成了1234,1243,1324,1342,1432,1423的输出。之后还需要通过swap函数交换回之前的状态,否则在之前的递归会出现重复的状况。

函数解答

perm函数有left和right两个参数,分别代表了此次全排列数组的范围。

从j=left开始进行每一个范围内的数组内容和第一个left内容交换,之后再对交换后的left+1到right的范围进行全排列。最后递归出口是left=right时,代表最后没有范围全排列了,这个时候的数组可以进行输出。输出过后,我们还需要对之前交换的内容进行交换回去。因为交换回去之后才会在新一轮j++后,最左端的a[left]保证是1,2,3……这样才不会重复。

否则 第一轮a[left]原本是1,不交换回去的话递归出口a[left]不确定是1还是2,3,4……,在第二轮j++循环后,无法确定从2开始,这样就会乱。

实验代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 7
void swap(int a[],int left,int right)
{
    int tmp;
    tmp = a[left];
    a[left] = a[right];
    a[right] = tmp;
}

//全排列
void pailie(int a[],int left,int right)
{
    int j,i;
    if(left<right)
    {
        for(j=left;j<right;j++)
        {
            swap(a,left,j);
            pailie(a,left+1,right);
            swap(a,j,left);
        }
    }
    else
    {
        for(i=0;i<MAXSIZE-1;i++)
        {
            printf("%5d",a[i]);
        }
        printf("\n");
    }
}
int main()
{
    int a[MAXSIZE] = {0,1,2,3,4,5,6};
    int i;
    printf("初始数组为:");
    for(i=0;i<MAXSIZE-1;i++)
    {
        printf("%5d",a[i]);
    }
    printf("\n");
    printf("全排列如下:\n");
    int left=0,right = MAXSIZE-1;
    //全排列
    pailie(a,left,right);
    return 0;
}
  • 12
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值