zoukankan      html  css  js  c++  java
  • 全排列之递归与非递归算法实现总结

    全排列之递归与非递归算法实现总结

     

    递归实现

    常见的是基于交换的,原理:从而可以推断,设一组数p = {r1, r2, r3, ... ,rn}, 全排列为perm(p),pn = p - {rn}。

    因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), ... , rnperm(pn)。当n = 1时perm(p} = r1。意思即是,将整组数中的所有的数分别与第一个数交换,这样就总是在处理后n-1个数的全排列, 如果有重复数字,则第一个数每次与后面的不同数字交换;

    关键代码

    Void perm(list,k,m)
    {
        If(k>m)  print(list)
            Else {
             For(i=k; i<=m;i++) {
            Swap(&list[k],&list[i])
            Perm(list,k+1,m)
            Swap(&list[k],&list[i])
            }
        }
    }
                        

     

    上面这种方法可以顺序打印出所有排列,但是无序的,也无法打印出第n个排列,下面这种递归实现可以升序打印出所有排列;如果要打印第n个排列,加一个计数器就可以,但需要先生成前n-1个排列,不划算;

    Vector result;  //存放一个排列
    Bool visited;  //初始化为false
    Void perm(list,n) 
    {
      If(result.size() >= n)  print(result)
       Else {
        For(i=0; i<n;i++) {
        If(visited[i] ) continue;
        Visited[i] = true;
        Perm(list,m)
        Visited[i] = false;
       }
     }
    }

     

    全排列的非递归实现可以借助下面的两个方法(代码略):

    方法一:生成下一个排列,该方法对重复元素同样有效

    如果可以根据一个排列生成他的下一个排列,那么生成所有排列也就不在话下了,下面以排列625431为例来说明怎么生成下一个排列,首先从右向左找到第一个降序对,这里是25,然后将前面的数字与其后面的大于它的最小数字相替换,这里是指将2与2后面的大于2的最小数字相替换,被替换数字是3,替换后的序列是635421,此时3后面的数字肯定是一个降序(从左到右)序列,将这个序列颠倒即可,得到631245,这就是625431的下一个序列,初始时应将元素排序,然后逐个生成;

    方法二:生成第n个排列

    m个元素的排列总数为m!; 假设m个元素初始时已经升序放入集合key中,则第n个排列的第一个元素必然是集合key中第n/(m-1)! 小元素,记为kx, 设定最小元素为第0小元素;接下来在集合key-{kx}中找出第n%(m-1)!个排列;以此类推,迭代找出所求排列的所有元素;

    如果有重复元素,则m个元素的排列总数为m1! /(c1! * c2! *….cn!),ci为元素ki的重复次数;集合key也是一个多重集,对重复元素每次也只删除一个;

     

    参考来源

    http://www.cnblogs.com/nokiaguy/archive/2008/05/11/1191914.html

    http://blog.csdn.net/morewindows/article/details/7370155/

  • 相关阅读:
    所谓经济现象
    高旻寺德林老和尚开示
    3Delight NSI: A Streamable Render API
    Play vue.js with constant value in SailsJS
    天魔心法之——识人篇
    对国内IoT的展望
    对国内AR产业的预言
    简评某中国工程师嫌疑窃取苹果自动驾驶技术
    评估人类的金三角模型
    Odoo 进销存报表现已开源
  • 原文地址:https://www.cnblogs.com/gaoyanqing/p/4312962.html
Copyright © 2011-2022 走看看