ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 2126|回复: 11

[求助] 求解释递归法的运用

[复制链接]

TA的精华主题

TA的得分主题

发表于 2020-1-18 14:29 | 显示全部楼层 |阅读模式
摁了F8逐步执行后,还没弄懂下面的 Function myCombination 是怎样执行的,求各位能帮忙解释代码是怎样执行的吗。
在 Function myCombination ,先开始执行Else 部分,
lngSelID =0,lngResultID =0, lngRow=0,arrResult=(0,0)=arrilist(0)  ,
lngResultID+1 后在循环,
lngSelID =0,lngResultID =1, lngRow=0,arrResult=(1,0)=arrilist(0)  ,
lngResultID+1 后  执行 If lngResultID > lngMax Then。。。。。这个时候lngResultID=2 > lngMax=1  ---->为什么这个执行后返回
lngSelID =0,lngResultID =1,lngCur=1 的?此时 为什么 lngResultI ≠2,而是 lngResultID =1。

另外一个问题:
在执行第一个 lngCur =2 后,为什么此处 lngCur =1, lngSelID =0,lngResultID =0,然后再继续执行?

---------------------------------------------------------------------------------------------------------------------------------------
Sub Test()
    Dim arrList As Variant
    Dim arrResult As Variant

    arrList = Array(0, 1, 2)
    myCombination arrList, 0, 0, 1, arrResult

    arrResult = Application.WorksheetFunction.Transpose(arrResult)
    ActiveSheet.Range("A1").Resize(UBound(arrResult) - 1, UBound(arrResult, 2)) = arrResult

End Sub
'----------------------------------------------------------------------------------------------------------------------------------------------------
Function myCombination(arrList As Variant, lngSelID As Long, lngResultID As Long, lngMax As Long, ByRef arrResult As Variant)
    Dim lngCur As Long, lngRow As Long, lngCol As Long
    If lngResultID > lngMax Then
            lngRow = UBound(arrResult, 2) + 1
        ReDim Preserve arrResult(0 To lngMax, 0 To lngRow)
        For lngCol = LBound(arrResult) To UBound(arrResult)
            arrResult(lngCol, lngRow) = arrResult(lngCol, lngRow - 1)
        Next
    Else
        If IsArray(arrResult) = False Then ReDim arrResult(0 To lngMax, 0 To 0)

        For lngCur = lngSelID To UBound(arrList)
            lngRow = UBound(arrResult, 2)
                arrResult(lngResultID, lngRow) = arrList(lngCur)
            myCombination arrList, lngCur, lngResultID + 1, lngMax, arrResult
        Next
    End If
End Function


TA的精华主题

TA的得分主题

发表于 2020-1-18 14:43 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
推荐你去网易云课堂搜索一下视频教程,杨洋老师的那个。里面讲解的比较详细又通俗易懂。

TA的精华主题

TA的得分主题

发表于 2020-1-18 15:42 | 显示全部楼层
F8 很難理解遞歸的,事實上也沒必要去看它的過程
複雜的是很難追蹤理解的,遞歸是在堆疊,不斷的堆疊過程,直到最後才由最後的開始返回最初
想用F8去理解複雜的幾乎不可能

TA的精华主题

TA的得分主题

发表于 2020-1-18 20:21 | 显示全部楼层
递归本来就很难理解,先用最简单的例子理解递归的原理,然后再逐步理解复杂的:
Option Explicit
Dim ar(), n&
Sub main()
    Dim num&
    n = 0
    num = 60
    Call recursive(num)
    MsgBox num & "的质因数是:" & Join(ar)
End Sub
Sub recursive(num)
    If num > 1 Then
        Dim i&
        For i = 2 To num
            If num / i = Int(num / i) Then Exit For
        Next i
        n = n + 1
        ReDim Preserve ar(1 To n)
        ar(n) = i
        Call recursive(num / i)
    End If
End Sub

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2020-1-19 08:59 | 显示全部楼层
要理解递归,可能要先理解 堆和栈 这两个概念,结合起来理解比较容易

TA的精华主题

TA的得分主题

发表于 2020-1-19 09:39 | 显示全部楼层
运用递归的一个简单的案例, 阶乘:
  1. <font face="Arial" size="3">Function f(n)</font>
复制代码


运用递归的思想解决汉诺塔问题,该例子是递归运用的一个经典案例
  1. <font size="3" face="Arial">Option Explicit
  2. Dim WAYSnbsp; '最终结果
  3. Dim SEPnbsp; '分隔符(仅适用于本例的排版需求)

  4. Private Sub Move(a$, b$)</font>
复制代码


评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2020-1-19 11:19 | 显示全部楼层
本帖最后由 huagou8 于 2020-1-19 11:25 编辑

个人觉得,你只需理解递归的原理就行了,具体的执行过程没必要追溯,人的大脑处理递归的层次不超过3层,3层以上完全懵逼。
楼上的同学举例很好,汉诺塔,经典的递归应用。下面是我自己写的两个函数,可以参考交流。
'汉诺塔解法函数
Function hanoi(n As Integer, a As String, b As String, c As String)
    Dim arr()
    If n = 1 Then hanoi = "moving " & n & " from " & a & " to " & c & " "
    If n > 1 Then hanoi = hanoi(n - 1, a, c, b) & Chr(10) & "moving " & n & " from " & a & " to " & c & " " & Chr(10) & hanoi(n - 1, b, a, c)
End Function
'汉诺塔解决步骤数
Function hanoistep(n As Integer)
    If n = 1 Then hanoistep = 1
    If n > 1 Then hanoistep = hanoistep(n - 1) * 2 + 1   
End Function

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2020-1-19 11:54 | 显示全部楼层
  1. '这是我写的一个函数,解决“vba怎样用指定3个数组合,每一行有4个数” http://club.excelhome.net/thread-1517516-1-1.html
  2. '
  3. '其实就是一个全排列的递归算法
  4. '
  5. '全排列算法是一种非常经典的递归算法
  6. '思路:
  7. '1、先固定第一个元素,求剩下的全排列
  8. '2、求剩下的全排列时,固定剩余元素中的第一个元素,再求剩下元素的全排列
  9. '3、重复以上思路,直到就剩一个元素停止。
  10. '
  11. '整个函数的意义
  12. '    从arrList数组中,抽取 lngMax+1个数,将结果返回arrResult 数组
  13. '
  14. '基础知识:
  15. '    (1)数组索引下限从0开始
  16. '    (2)多维数组只能改变最后的维度。如果是二维数组,且EXCEL的概念就是:行固定,列增加。


  17. Function myCombination(arrList As Variant, lngSelID As Long, lngResultID As Long, lngMax As Long, ByRef arrResult As Variant)
  18.     Dim lngCur As Long, lngRow As Long, lngCol As Long
  19.     '边界条件:
  20.     '   要取的个数已满足条件,则输出
  21.     If lngResultID > lngMax Then
  22.         '只能变更最后的维度
  23.         lngRow = UBound(arrResult, 2) + 1
  24.         '第二维对应最终结果是 行,所以定义名称lngRow
  25.         ReDim Preserve arrResult(0 To lngMax, 0 To lngRow)
  26.         For lngCol = LBound(arrResult) To UBound(arrResult)
  27.             arrResult(lngCol, lngRow) = arrResult(lngCol, lngRow - 1)
  28.         Next
  29.     Else
  30.         If IsArray(arrResult) = False Then ReDim arrResult(0 To lngMax, 0 To 0)
  31.         '循环读取arrList数组中的内容,赋值于当前行
  32.         For lngCur = lngSelID To UBound(arrList)
  33.             lngRow = UBound(arrResult, 2) '读取arrResult的第二维,就是现在的列号,将来的行号
  34.             arrResult(lngResultID, lngRow) = arrList(lngCur) '在当前列(lngRow)的指定行(lngResultID)赋值
  35.             myCombination arrList, lngCur, lngResultID + 1, lngMax, arrResult '行+1后,自身再调用
  36.         Next
  37.     End If
  38. End Function



  39. Sub Test()
  40.     Dim arrList As Variant
  41.     Dim arrResult As Variant

  42. '    arrList = Array(0, 1, 2, 3)
  43. '    myCombination arrList, 0, 0, 4, arrResult
  44.     arrList = Array(0, 1, 2)
  45.    
  46.     myCombination arrList, 0, 0, 3, arrResult
  47.    
  48.     arrResult = Application.WorksheetFunction.Transpose(arrResult)
  49.    
  50.     Sheet1.UsedRange.Clear
  51.     '想一下,这里的行数为什么要减1
  52.     Sheet1.Range("A1").Resize(UBound(arrResult) - 1, UBound(arrResult, 2)) = arrResult
  53.     MsgBox "OK"
  54. End Sub


  55. '【myCombination arrList, 0, 0, 3, arrResult】运行结果

  56. '     ***arrlist=[0,1,2] 不变

  57. '(1)arrResult=[0,,,]  调用 myCombination arrList, 0, 1, 3, arrResult
  58. '(2)arrResult=[0,0,,]  调用 myCombination arrList, 0, 2, 3, arrResult
  59. '(3)arrResult=[0,0,0,]  调用 myCombination arrList, 0, 3, 3, arrResult
  60. '(4)arrResult=[0,0,0,0]  调用 myCombination arrList, 0, 4, 3, arrResult
  61. '(5)此时lngResultID(4)>lngMax(3)
  62. '      arrResult增加一维 =[0,0,0,0][0,0,0,0]  ,退出当前调用函数,执行for循环,相当于lngCur+1=1,arrlist[1]=1
  63. '               arrResult=[0,0,0,0][0,0,0,1]  调用 myCombination arrList, 1, 4, 3, arrResult
  64. '     此时,lngResultID(4)>lngMax(3)
  65. '      arrResult增加一维 =[0,0,0,0][0,0,0,1][0,0,0,1]  ,退出当前调用函数,执行for循环,相当于lngCur+1=2,arrlist[2]=1
  66. '               arrResult=[0,0,0,0][0,0,0,1][0,0,0,2]  调用 myCombination arrList, 2, 4, 3, arrResult
  67. '     此时,lngResultID(4)>lngMax(3)
  68. '      arrResult增加一维 =[0,0,0,0][0,0,0,1][0,0,0,2][0,0,0,2]  ,退出当前调用函数,完成当前的for循环,返回上层循环
  69. '               arrResult=[0,0,0,0][0,0,0,1][0,0,0,2][0,0,0,2]  调用 myCombination arrList, 1, 3, 3, arrResult
  70. '               arrResult=[0,0,0,0][0,0,0,1][0,0,0,2][0,0,1,1]  调用 myCombination arrList, 1, 4, 3, arrResult
  71. '      arrResult增加一维 =[0,0,0,0][0,0,0,1][0,0,0,2][0,0,1,1][0,0,1,1]  ,退出当前调用函数,完成当前的for循环,返回上层循环
  72. '               arrResult=[0,0,0,0][0,0,0,1][0,0,0,2][0,0,1,1][0,0,1,2] 调用 myCombination arrList, 2, 4, 3, arrResult
  73. '      arrResult增加一维 =[0,0,0,0][0,0,0,1][0,0,0,2][0,0,1,1][0,0,1,2][0,0,1,2]  ,退出当前调用函数,完成当前的for循环,返回上层循环
  74. '               arrResult=[0,0,0,0][0,0,0,1][0,0,0,2][0,0,1,1][0,0,1,2][0,0,2,2] 调用 myCombination arrList, 2,3, 3, arrResult
  75. '               arrResult=[0,0,0,0][0,0,0,1][0,0,0,2][0,0,1,1][0,0,1,2][0,0,2,2] 调用 myCombination arrList, 2,4, 3, arrResult
  76. '
  77. '不停循环
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-1-20 14:54 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-1-20 15:21 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册

因为arrResult 数组是从0开始,下一个数组的值等于上一个数组的值,最后就产生了最后一个数组和上一个数组的值相同,所以要减1
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

最新热点上一条 /1 下一条

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-24 13:28 , Processed in 0.039299 second(s), 17 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表