zoukankan      html  css  js  c++  java
  • 全排列

    全排列的递归实现虽然简单,但不容易理解。在绘制了一个树形结构图后,终于看清了里面的计算过程。但是虽然理清了过程,还是不明白为什么会这样设计。尤其是在递归调用的前后分别进行一次交换操作,感觉总是摸不着头绪。内心深处有个声音,往往让你绞尽脑汁不得其解的问题越是你的软肋。记得在高中学数学的时候,往往会因为一个数学难题而想破头想一个晚上,最终解出来之后总有种任通二脉打开的感觉,会感觉之前做过的类似的问题也会豁然开朗很多,虽然浪费了很长时间在这一个问题上,但收获却是无法估量的。

    工作之后,很难静下心来思考一个问题很长时间,尤其是算法问题。这就是考验一个人的关键时刻。静下心来,认真思考,浮躁只会让自己的困惑越积越多,直到困惑足以打破你的自信心,你就永远都无法在这个地方抬起头来!

    回头来思考这个问题,看到这个图之后清晰多了。我们看到,

    (1)以a开头后面跟着(b,c,d)的排列

    (2)以b开头后面跟着(a,c,d)的排列

    (3)以c开头后面跟着(a,b,d)的排列

    (4)以d开头后面跟着(a,b,c)的排列

    当前元素与它后面的元素(包含它自己)依次进行交换

    第一个swap是进行交换,而第二个swap是上一次swap的逆操作,为了防止上一次swap对之后产生影响。

    template <class T>
    inline void Swap(T& a, T& b)
    {
        // 交换a和b
        T temp = a; a = b; b = temp;
    }
     
    template<class T>
    void Perm(T list[], int k, int m)
    {
        //生成list [k:m ]的所有排列方式
        int i;
        if (k == m)
        {
             //输出一个排列方式
             for (i = 0; i <= m; i++)
                 cout << list [i];
             cout << endl;
        }
        else // list[k:m]有多个排列方式
        {
             // 递归地产生这些排列方式
             for (i=k; i <= m; i++)
             {
                 Swap (list[k], list[i]);
                 Perm (list, k+1, m);
                 Swap (list[k], list[i]);
             }
        }
    }

    非递归算法的实现过程

    //交换数组a中下标为i和j的两个元素的值
    void swap(int* a,int i,int j)
    {
        a[i]^=a[j];
        a[j]^=a[i];
        a[i]^=a[j];
    }
     
    //将数组a中的下标i到下标j之间的所有元素逆序倒置
    void reverse(int a[],int i,int j)
    {
        for(;i<j;++i,--j)
        {
             swap(a,i,j);
        }
    }
     
    void print(int a[],int length)
    {
        for(int i=0;i<length;++i)
             cout<<a[i]<<" ";
        cout<<endl;
    }
     
    //求取全排列,打印结果
    void combination(int a[],int length)
    {
        if(length<2) return;
     
        bool end=false;
        while(true)
        {
             print(a,length);
            
             int i,j;
             //找到不符合趋势的元素的下标i
             for(i=length-2;i>=0;--i)
             {
                 if(a[i]<a[i+1]) break;
                 else if(i==0) return;
             }
     
             for(j=length-1;j>i;--j)
             {
                 if(a[j]>a[i]) break;
             }
            
             swap(a,i,j);
             reverse(a,i+1,length-1);
        }
    }
  • 相关阅读:
    Asp.net 动态添加Meta标签
    【转】在SharePoint Server 2010中更改“我的网站”
    SPQuery DateTime 类型查询
    Asp.net Web Application 打开 SharePoint 2010 Site 错误 The Web application at could not be found
    How To Create SharePoint 2010 Site Collection In Its Own DB
    C# 文件打印
    面试题 java集合
    《深入理解Java虚拟机》(六)堆内存使用分析,垃圾收集器 GC 日志解读
    《深入理解Java虚拟机》(五)JVM调优
    《深入理解Java虚拟机》(四)虚拟机性能监控与故障处理工具
  • 原文地址:https://www.cnblogs.com/sdlwlxf/p/4645917.html
Copyright © 2011-2022 走看看