zoukankan      html  css  js  c++  java
  • 非递归实现不重复序列的全排列(三)

    ?笔者曾利用进制转换实现不重复序列全排列(http://blog.csdn.net/northwolves/archive/2004/07/21/47400.aspx),但从0 循环到n^(n-1)-1,效率实在不高,经过仔细分析,发现一个另人激动的规律,详情见下表:

    ?

    A

    ?

    BA

    CBA

    DCBA

    CDBA

    CBDA

    CBAD

    BCA

    DBCA

    BDCA

    BCDA

    BCAD

    BAC

    DBAC

    BDAC

    BADC

    BACD

    AB

    CAB

    DCAB

    CDAB

    CADB

    CABD

    ACB

    DACB

    ADCB

    ACDB

    ACBD

    ABC

    DABC

    ADBC

    ABDC

    ABCD

    从上面表格可以看出,对于“ABCD”,假如先放好A(只有一种放法),再放B时,可以有BA,AB两种放法;再放C时,则针对BA,AB 各有3种放法(BA前,BA中,BA后),再放D时,各有4种放法。所以第一个元素排好后,第2个元素的位置可以用0,1 表示,第3个元素的位置可以用0,1 ,2表示,第n个元素的位置可以用0,1 ,2,3,...n-1表示,因而使用混合进制(笔者起的名字)可以实现数组元素的全排列。

    代码如下:

    Sub pailie3(ParamArray x())
    Dim starttime As Single, endtime As Single
    Dim i As Integer, j As Integer, Num As Long, n As Integer
    Dim ALL As New Collection, TEMP1 As Long, TEMP2 As Long
    n = UBound(x) + 1 '元素个数
    starttime = Timer '开始计时
    Num = 1
    For i = 1 To n
    Num = Num * i? '递归计算n!
    Next
    For i = 1 To Num
    Set ALL = Nothing '初始化集合all
    ALL.Add x(0)
    TEMP1 = i
    For j = 2 To n
    TEMP2 = TEMP1 Mod j
    TEMP1 = TEMP1 / j
    If TEMP2 = 0 Then
    ALL.Add x(j - 1) 'temp2为 0则放在最后
    Else
    ALL.Add x(j - 1), , BEFORE:=TEMP2 'temp2不为 0 则置于第temp2个元素前
    End If
    Next
    For j = 1 To n
    Debug.Print ALL(j) & " "; '输出
    Next
    Debug.Print
    Next
    endtime = Timer
    Debug.Print "共 " & Num & " 种排列!用时 " & endtime - starttime & " 秒!"
    End Sub

    Private Sub Command1_Click()
    pailie3 "a", "b", "c", "d", "e", "f", "g"
    End Sub

    ?

    由于集合属于VARIANT类型,运算速度慢,换成数组进行同样的转换,发现确实快了很多:

    Sub pailie4(ParamArray x())
    Dim starttime As Single, endtime As Single
    Dim i As Integer, j As Integer, k As Integer, Num As Long, n As Integer
    Dim ALL(), TEMP1 As Long, TEMP2 As Long
    n = UBound(x) + 1 '元素个数

    starttime = Timer '开始计时
    Num = 1
    For i = 1 To n
    Num = Num * i? '递归计算n!
    Next
    For i = 1 To Num
    ReDim ALL(1 To n) '初始化数组all
    ALL(1) = x(0)
    TEMP1 = i
    For j = 2 To n
    TEMP2 = TEMP1 Mod j
    TEMP1 = TEMP1 / j
    If TEMP2 = 0 Then
    ALL(j) = x(j - 1) 'temp2为 0则放在最后
    Else
    For k = j To TEMP2 + 1 Step -1
    ALL(k) = ALL(k - 1)? ' temp2之后的元素后移一位
    Next
    ALL(TEMP2) = x(j - 1) 'temp2不为 0 则置于第temp2个元素前
    End If
    Next
    Debug.Print Join(ALL, " ")? '输出
    Next
    endtime = Timer
    Debug.Print "共 " & Num & " 种排列!用时 " & endtime - starttime & " 秒!"
    End Sub
    Private Sub Command1_Click()
    pailie4 "a", "b", "c", "d", "e", "f", "g"
    End Sub

    如果用COPYMEMORY进行数组的移动,速度应该更快,大家有兴趣不妨一试。

  • 相关阅读:
    java中ant包中的org.apache.tools.zip实现压缩和解压缩
    velocity.properties配置说明
    序列化人人网框架下的DAO?也就是在Spring下序列化DAO的问题(spring+quartz集群下)
    vue-cli使用sockjs即时通信
    VUE温习:nextTick、$refs、嵌套路由、keep-alive缓存、is特性、路由属性用法、路由钩子函数
    win7下Google谷歌浏览器上传下载卡死无响应
    微信支付开发流程
    阿里云视频点播同层播放问题
    微信小程序 scroll-view 实现锚点跳转
    解决微信小程序ios端滚动卡顿的问题
  • 原文地址:https://www.cnblogs.com/fengju/p/6336391.html
Copyright © 2011-2022 走看看