全排列问题(递归&非递归&STL函数)

问题描述:

打印输出1-9的所有全排序列,或者打印输出a-d的全排列。

思路分析:

将每个元素放到余下n-1个元素组成的队列最前方,然后对剩余元素进行全排列,依次递归下去。

比如:1 2 3 为例
首先将1放到最前方(跟第1个元素交换),然后后面2位再做全排,然后将1放回本来位置 
结果 1 2 3; 1 3 2
其次将2放到最前方(跟第1个元素交换),然后后面2位再做全排,然后将2放回原处
结果 2 1 3; 2 3 1
。。。。。

 

C/C++递归实现:

#include<cstdio>
#include<iostream>
using namespace std;

void swap(int list[], int i, int j)  //交换list中i和j位置的元素
{
    int temp = list[i];
    list[i] = list[j];
    list[j] = temp;
}

void fun(int list[], int m, int n)  //输出list中m到n的全排列
{
    if(m==n)
    {
        for(int i=0; i<n; i++)   //输出0-n的一个排列
        {
            printf("%d",list[i]);
        }
        printf("\n");
    }
    else
    {
        for(int i=m; i<n; i++)
        {
            swap(list,m,i);  //把第i个和第一个(此时是m)交换
            fun(list,m+1,n);  //余下的继续递归
            swap(list,m,i);   //将第i个放回原处
        }
    }
}

int main()
{
    int list[] = {1,2,3,4,5,6};
    int length = sizeof(list)/sizeof(list[0]);
    fun(list,0,length);
    return 0;
}

 

C/C++非递归实现:(当输入中数字有重复数字时仍能正常工作,即不会有重复输出)

/*完全参考:http://blog.csdn.net/prstaxy/article/details/8147029*/

#include<iostream>  
#include<algorithm>    
#include<vector>    
using namespace std;    
bool next(vector<int> &v)//注意是引用     
{    
    int i;    
    for(i=v.size()-1;i>=1;i--)    
    {//从数组后面往前找到第一个比后面的数小的地方     
        if(v[i-1]<v[i])     
            break;    
    }    
    if(i==0)//整个数组都是逆序,说明是已是排列最后一个     
        return false;//没有下一个     
    else    
    {    
        int t=v[i-1],pos=i;    
        for(int j=i;j<v.size();j++)    
        {    
            if(v[j]>t && v[j]<=v[pos])//再往后找比v[i-1]大的数中最小的一个 //2014.10.1把<改成<=,否则输入有重复数字时会出现bug  
                pos=j;    
        }    
        v[i-1]=v[pos];    
        v[pos]=t;//交换     
        //sort(v.begin()+i,v.end());//从小到达排序  
        reverse(v.begin()+i,v.end());//此时正好逆序,只需反转即可从小到达排序   
        return true;//还有下一个     
    }    
}    
void printVctor(vector<int> v)    
{    
    for(int i=0;i<v.size();++i)    
        cout<<v[i]<<" ";    
    cout<<endl;    
}    
int main()    
{    
    int a[] = {1,2,3,4,5};    
    vector<int> v(a,a+5);    
    do    
    {    
        printVctor(v);    
    }while(next(v));    
    return 0;    
}    
非递归实现

 

C++ STL代码实现:

C++ STL中算法库中包含了计算排列组合关系的算法next_permutation、prev_permutation,用法如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;

int main()
{
    int list[] = {1,2,3,4,5,6};
    int length = sizeof(list)/sizeof(list[0]);
    sort(list, list+length);  /* 这个sort可以不用,因为{1,2,3,4}已经排好序*/ 
    do                        /*注意这步,如果是while循环,则需要提前输出第一个次序*/
    {
        for(int i=0; i<length; i++)
        {
            printf("%d",list[i]);
        }
        printf("\n");
    }while(next_permutation(list,list+length));
    //while(prev_permutation(list,list+length));//求上一个排列数,初始数组用逆序来调用可以输出全排列 
    return 0;
}

 

 

 

参考链接:

next_permutation(全排列算法)     http://blog.csdn.net/c18219227162/article/details/50301513

上面这个链接开始介绍了排列组合是如何区分前一个后一个的,也就是如何排序的; 最后还包含一个 “直接算出集合{1, 2, ..., m}的第n个排列” 的代码实现

 

http://blog.csdn.net/prstaxy/article/details/8147029

http://blog.csdn.net/knisinf/article/details/48048011

 

 

转载于:https://www.cnblogs.com/tanrong/p/8471115.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值