zoukankan      html  css  js  c++  java
  • 全排列问题(递归&非递归&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("
    ");
        }
        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("
    ");
        }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

     

     

  • 相关阅读:
    函数传参总结
    集合操作总结
    深浅拷贝总结
    三级列表展示
    文件操作总结
    vue-router之嵌套路由
    vue-router之动态路由
    Sublime编辑VUE实现代码高亮
    Windows系统下Vue开发环境搭建详解版
    C#调用快递鸟电子面单API实现批量打印电子面单功能
  • 原文地址:https://www.cnblogs.com/tanrong/p/8471115.html
Copyright © 2011-2022 走看看