ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[讨论] 来个难度高点的:用最快的方法找出一个树内距离最远的两个节点间的距离

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2023-9-1 11:41 | 显示全部楼层
昨天写了一个,稍大数据(5000左右节点)验证中。

TA的精华主题

TA的得分主题

发表于 2023-9-1 12:54 | 显示全部楼层
昨天用本贴1楼的随机数生成工具做了一下测试,7000多个节点的情况下,得到的最大两点距离为10,第一感觉比较离谱,后来一分析也可能是正确的。
目前的生成工具,是每个节点随机生成1~10个分支,按平均5个算,5、25、125、625、3125、15625(已超过测试所需节点数),根节点到最远端只有5个距离,那两个最远点就是在距离10左右。
另外,如果是随机树的话,实际上每个循环剪除的叶子数是非常多的,树复杂度会呈指数级下降(如上数据的话,第1次可剪除15625个叶子),个人认为效率较高。

TA的精华主题

TA的得分主题

发表于 2023-9-1 21:05 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 大灰狼1976 于 2023-9-1 21:49 编辑
时间的音符 发表于 2023-9-1 09:10
..............................

楼上SQL高手的答案先不说,因为我目前还看不懂,你的附件测试了一下,使用同一个树数据,得出的3个结果都是相同的,应该没有错误。又想了一下,还有简化的空间,原来想的每个分枝处保留两个最长节点数据,实际上仔细想了一下,这个是不需要的,如果这两个点就是树的最大距离点,反正临时变量里会记录,如果它不是,在向上层父节点传递数据时,会舍去距离较小的点,保留两个没有必要。

TA的精华主题

TA的得分主题

发表于 2023-9-1 21:27 | 显示全部楼层
本帖最后由 大灰狼1976 于 2023-9-1 21:51 编辑

全部揉进了一个function,3个函数中我最慢。
  1. Public Function LongestPath(ByVal strTree As String) As String 'Long
  2. Dim arrTmp, aTmp, arrMain, Dis&, i&, d As Object, c, disTmp&, sTmp$
  3. Dim longestPnt$, parentPnt$, thisDis&, longestTmp(2), lTmp&
  4. Set d = CreateObject("scripting.dictionary")
  5. Dis = 1   '可扩展功能,strTree内可追加每个节点间的非固定距离如:"2;1;3,3;1;2,4;1;5"
  6. arrTmp = Split(strTree, ";")
  7. ReDim arrMain(1 To arrTmp(0), 2)
  8. For i = 1 To UBound(arrTmp)
  9.   aTmp = Split(arrTmp(i), ",")
  10.   arrMain(aTmp(0), 0) = arrMain(aTmp(0), 0) & "," & aTmp(1) & ";" & Dis
  11.   d(aTmp(0)) = d(aTmp(0)) + 1
  12.   arrMain(aTmp(1), 0) = arrMain(aTmp(1), 0) & "," & aTmp(0) & ";" & Dis
  13.   d(aTmp(1)) = d(aTmp(1)) + 1
  14. Next i
  15. Retry:
  16. For Each c In d.keys
  17.   If d(c) = 1 Then
  18.     sTmp = arrMain(c, 0)
  19.     parentPnt = Val(Mid(sTmp, 2))
  20.     thisDis = Split(sTmp, ";")(1)
  21.     If arrMain(c, 1) <> "" Then
  22.       longestPnt = arrMain(c, 1)
  23.       disTmp = arrMain(c, 2) + thisDis
  24.     Else
  25.       longestPnt = c
  26.       disTmp = thisDis
  27.     End If
  28.     If arrMain(parentPnt, 1) = "" Then
  29.       arrMain(parentPnt, 1) = longestPnt
  30.       arrMain(parentPnt, 2) = disTmp
  31.     Else
  32.       If disTmp + arrMain(parentPnt, 2) > longestTmp(2) Then
  33.         longestTmp(0) = arrMain(parentPnt, 1)
  34.         longestTmp(1) = longestPnt
  35.         longestTmp(2) = disTmp + arrMain(parentPnt, 2)
  36.       End If
  37.       If disTmp > arrMain(parentPnt, 2) Then arrMain(parentPnt, 2) = disTmp: arrMain(parentPnt, 1) = longestPnt
  38.     End If
  39.     d(parentPnt) = d(parentPnt) - 1
  40.     d.Remove c
  41.     arrMain(parentPnt, 0) = Replace(arrMain(parentPnt, 0), "," & c & ";" & thisDis, "")
  42.   End If
  43. Next c
  44. If d.Count > 1 Then GoTo Retry
  45. LongestPath = Join(longestTmp, ",")
  46. End Function
复制代码
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-5-19 11:15 , Processed in 0.041548 second(s), 6 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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