当前位置: 首页 > news >正文

Excel·VBA数组排列函数

目录

    • 1,组合代码思路
    • 2,VBA数组排列函数
    • 3,VBA数组重复排列函数

上一篇文章《Excel·VBA数组组合函数、组合求和》,实现了VBA组合功能,本文为VBA排列功能

《百度百科-排列》
排列:从n个不同元素中,取出m(m≤n)个元素,按照一定的顺序排成一列,叫做从n个元素中取出m个元素的一个排列,一般称作选排列;当m=n时,这个排列被称作全排列
排列数:从n个不同元素中取出m个不同元素的所有不同排列的个数称为排列种数或称排列数
排列个数公式:P(n,m) = n!/(n-m)!,当n=m即全排列时为P(n) = n!

1,组合代码思路

从1-5共5个数字中选出4个数字,共120种排列,如图(部分截图)
在这里插入图片描述
按照上一篇文章“VBA组合函数”尾数循环的方式,观察每个排列的数字排列规律,可以发现每次尾数循环结束后,倒数第2列(即m-1)即进位+1(即2-3行);当进位列的数字达到最大值(即n)时,继续向前1列(即m-2)进位+1(即6-7行);当进位后的数字在之前出现过时,数字继续递增+1(即8-9行);进位结束后,排列在进位点之前的数字不变,之后的数字,按照1-5的顺序填入,且数字不重复;如此循环直至完成120种排列

VBA代码如下

2,VBA数组排列函数

选排列、全排列

Function permut_arr(arr, n&)
    'arr一维数组,内含m个元素,抽取n个进行排列,返回一维嵌套数组,每行为一个排列(数组从1开始计数)
    Dim i&, j&, k&, m&, kk&, result, x&, r&
    If LBound(arr) = 0 Then  '转为从1开始计数
        arr = WorksheetFunction.Transpose(WorksheetFunction.Transpose(arr))
    End If
    m = UBound(arr) - LBound(arr) + 1: ReDim brr&(1 To m): ReDim b&(1 To n)
    kk = Application.permut(m, n): ReDim result(1 To kk): ReDim res(1 To n)
    If n = 1 Then
        For i = 1 To m
            result(i) = WorksheetFunction.Transpose(WorksheetFunction.Transpose(Array(arr(i))))
        Next
        permut_arr = result: Exit Function
    End If
    
    For i = 1 To m  'arr初始位置brr
        brr(i) = i
    Next
    Do
        For i = 1 To n - 1  'b非尾数部分
            b(i) = brr(i)
        Next
        For j = n To m   '仅修改尾数
            b(n) = brr(j)
            For k = 1 To n
                res(k) = arr(b(k))
            Next
            r = r + 1: result(r) = res
        Next
        x = n - 1: brr(x) = brr(x) + 1  '尾数循环结束后,n-1位进位
        y = Application.Match(brr(x), brr, 0)
        Do While (TypeName(y) <> "Error" And y < x) Or brr(x) > m
            If y < x Then brr(x) = brr(x) + 1  '进位后,如之前位有重复值的继续+1
            '循环进位,直至完成所有进位
            If brr(x) > m Then If x > 1 Then x = x - 1: brr(x) = brr(x) + 1 Else Exit Do
            y = Application.Match(brr(x), brr, 0)
        Loop
        If brr(1) > m Then Exit Do  '所有排列完成
        For i = 1 To m     '对brr数组x之后的按顺序赋值
            exist = False  '初始为不存在
            For j = 1 To x
                If brr(j) = i Then exist = True: Exit For
            Next
            If exist = False And x < m Then x = x + 1: brr(x) = i
        Next
    Loop Until r = kk
    permut_arr = result
End Function

注意:代码中“排列个数”kk定义为Long类型,故最大值为2,147,483,647,如果实际应用中会超过该值的,需修改数据类型

Sub permut_arr测试()
    Dim arr, brr
    tm = Timer
    arr = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
    brr = permut_arr(arr, 6)
    For Each b In brr
        r = r + 1: Cells(r, "a").Resize(1, UBound(b)) = b
    Next
    Debug.Print ("所有选排列写入完成,用时:" & Format(Timer - tm, "0.00"))
'--------------------转二维数组写入
'    tm = Timer
'    arr = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
'    brr = TransposeArr(permut_arr(arr, 6), 2)  '调用函数,将一维嵌套数组转为二维数组
'    Cells(1, "a").Resize(UBound(brr), UBound(brr, 2)) = brr
'    Debug.Print ("所有选排列写入完成,用时:" & Format(Timer - tm, "0.00"))  '耗时
End Sub

注意:测试中调用了TransposeArr函数,将一维嵌套数组转为二维数组输出,代码详见《Excel·VBA数组组合函数、组合求和》

测试在excel表格中输出0-9共10个数字选6的排列形式,共151200种排列,输出结果与python的结果完全一致
python排列:《python排列组合函数》

3种输出排列方式耗时对比:151200种排列耗时秒数

python排列VBA排列一维嵌套数组VBA排列一维嵌套数组转二维数组
15.55.161.46

可以看出,VBA排列输出一维嵌套数组2种写入方式都是非常快的

3,VBA数组重复排列函数

重复排列,相比上面的“选排列”和“全排列”是一种特殊的排列
重复排列:从n个不同元素中可重复地选取m个元素,按照一定的顺序排成一列,称作从n个元素中取m个元素的可重复排列
重复排列个数公式:n ^ m
代码思路:重复排列由于元素可重复使用,因而代码思路类似“选排列”,但仅考虑进位无需判断是否重复,仅原位置重置即可,故此代码较为简单(与10进制数字进位类似)

Function permut_repet(arr, n&)
    'arr一维数组,内含m个元素,重复抽取n个进行排列,返回一维嵌套数组,每行为一个排列(数组从1开始计数)
    Dim i&, m&, kk&, result, x&, r&
    If LBound(arr) = 0 Then  '转为从1开始计数
        arr = WorksheetFunction.Transpose(WorksheetFunction.Transpose(arr))
    End If
    m = UBound(arr) - LBound(arr) + 1: ReDim b&(1 To n)
    kk = m ^ n: ReDim result(1 To kk): ReDim res(1 To n)
    
    For i = 1 To n  '临时位置,index初始值
        b(i) = 1
    Next
    Do
        For i = 1 To n
            res(i) = arr(b(i))
        Next
        r = r + 1: result(r) = res
        x = n: b(x) = b(x) + 1   '修改尾数;当尾数循环结束后,进位
        Do While b(x) > m        '进位,b中元素的最大值是m,从后向前判断
            b(x) = 1: x = x - 1  '尾数重置,进位
            If x = 0 Then Exit Do  '完成所有排列
            b(x) = b(x) + 1
        Loop
    Loop Until r = kk
    permut_repet = result
End Function

注意:代码中“排列个数”kk定义为Long类型,故最大值为2,147,483,647,如果实际应用中会超过该值的,需修改数据类型

Sub permut_repet测试()
    Dim arr, brr
    tm = Timer
    arr = Array(1, 2, 3, 4, 5)
    brr = permut_repet(arr, 3)
    For Each b In brr
        r = r + 1: Cells(r, "a").Resize(1, UBound(b)) = b
    Next
    Debug.Print ("所有重复排列写入完成,用时:" & Format(Timer - tm, "0.00"))
End Sub

从1-5共5个数字中重复选出3个数字,共125种排列,如图(部分截图)
在这里插入图片描述

相关文章:

  • 高级程序员项目经理写好代码必备的三条基本素质;以及代码的现象和本质问题解读;
  • 猿创征文|多模态图像合成和编辑(MISE):Multimodal Image Synthesis and Editing: A Survey
  • 网络与信息安全基础知识-- Internet及应用
  • 中秋邀请共赏图数据库-蚂蚁集团图数据TuGraph 正式开源
  • GD32F303固件库开发(14)----IIC之配置OLED
  • LeetCode 0231. 2 的幂
  • 【LeetCode】螺旋矩阵旋转图像
  • 猿创征文|网络原理——UDP/TCP协议
  • 理论第七课——sort
  • PyCharm利用pydevd-pycharm实现Python远程调试
  • Mysql中DQL(查询类)语句的执行顺序
  • CMake Tutorial 巡礼(2)_添加库
  • java毕业设计蛋糕店会员系统Mybatis+系统+数据库+调试部署
  • IntelliJ IDEA中构建Spring Boot的项目
  • 计算机视觉项目-实时目标追踪
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • css布局,左右固定中间自适应实现
  • happypack两次报错的问题
  • javascript 总结(常用工具类的封装)
  • Laravel Mix运行时关于es2015报错解决方案
  • learning koa2.x
  • React Native移动开发实战-3-实现页面间的数据传递
  • storm drpc实例
  • 阿里云Kubernetes容器服务上体验Knative
  • 分布式熔断降级平台aegis
  • 普通函数和构造函数的区别
  • 驱动程序原理
  • 设计模式走一遍---观察者模式
  • 手机app有了短信验证码还有没必要有图片验证码?
  • 运行时添加log4j2的appender
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • (12)目标检测_SSD基于pytorch搭建代码
  • (2)STL算法之元素计数
  • (4)Elastix图像配准:3D图像
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (一)kafka实战——kafka源码编译启动
  • (一)WLAN定义和基本架构转
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • .net core Swagger 过滤部分Api
  • .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换
  • .Net6使用WebSocket与前端进行通信
  • .Net调用Java编写的WebServices返回值为Null的解决方法(SoapUI工具测试有返回值)
  • [ vulhub漏洞复现篇 ] Apache Flink目录遍历(CVE-2020-17519)
  • [ 云计算 | AWS ] AI 编程助手新势力 Amazon CodeWhisperer:优势功能及实用技巧
  • [<事务专题>]
  • [Big Data - Kafka] kafka学习笔记:知识点整理
  • [BZOJ2281][SDOI2011]黑白棋(K-Nim博弈)
  • [BZOJ5125]小Q的书架(决策单调性+分治DP+树状数组)
  • [C#]winform部署PaddleOCRV3推理模型
  • [DevEpxress]GridControl 显示Gif动画
  • [IE 技巧] 显示/隐藏IE 的菜单/工具栏
  • [Latex] Riemann 问题中的激波,接触间断,膨胀波的 Tikz 绘图