ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[讨论] 排序算法学习

[复制链接]

TA的精华主题

TA的得分主题

发表于 2019-10-1 10:31 | 显示全部楼层
aoe1981 发表于 2019-10-1 09:58
您才是高手,写出的代码思路新奇,让人大开眼界!
(1)temp = Application.Lookup(arr(i, 1), brr)旨在 ...

字典dic 用于 去重、 累加,其key顺序等同 arr,由小到大则是数组brr。
函数Lookup 曾写过一个自定义函数有点印象,它适用更多类型的数据, 二分法查找效率 也比遍历高 ,。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-10-1 14:28 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
关于“二叉查找树排序”有一点需要补充:
以10000个=RANDBETWEEN(1,10000)随机整数为例测试。

1.当序列为乱序:用时0.1171875秒;

2.当序列为顺序:用时12.34375秒;

3.当序列为倒序:用时7.59765625秒。

显然,“二叉查找树排序”在最坏情况下效率并不理想(与希尔、归并、快速、堆排对比),因为此时的二叉查找树长成了一条长长的链状。如果是顺序,则是一捺,向右下伸展;如果是倒序,则是一撇,向左下伸展。我猜测性分析:影响“二叉查找树”效率的关键是“叶子节点”数量的多少,所谓“叶子节点”,是无左右孩子的,也就是说,某一条从根节点出发的路径到达叶子节点就到了寻找的尽头。叶子节点只访问一次就被记录进有序区,其他节点则访问一次以上,回溯一次以上。链状二叉树中,叶子节点只有一个,其他节点一律访问一次,回溯一次,可能总次数居多吧。

再看看“堆”这种二叉树的排序:
1.乱序序列:0.16015625秒;
2.顺序序列:0.16796875秒;
3.倒序序列:0.16015625秒。
几乎不受影响,十分稳定,这又使我对“堆”刮目相看!!!

TA的精华主题

TA的得分主题

发表于 2019-10-2 08:46 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
数据拉满 111.jpg
100万组有重复数字 ,测试字典排序,
222.jpg



TA的精华主题

TA的得分主题

发表于 2019-10-2 20:11 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
记录下,空了研究

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-10-3 22:40 | 显示全部楼层
本帖最后由 aoe1981 于 2019-10-4 09:31 编辑
zopey 发表于 2019-10-2 08:46
数据拉满
100万组有重复数字 ,测试字典排序,

受您的启发,又做了一个“二分查找插入排序”,这个算法可以设计成稳定的,它像希尔一样,是对普通插入排序的一种改进,由于采用递归二分查找的方法,比普通插入法把有序区“从后至前扫描”的方法节省时间,但优化效果比不上希尔排序,果然“希尔排序”更加地大名鼎鼎。
10000个=RANDBETWEEN(1,10000)随机整数测试结果如下:
插入排序(5.2890625秒)>二分查找插入排序(2.65625秒)>希尔排序(0.234375秒)
30000个=RANDBETWEEN(1,10000)随机整数测试结果如下:
插入排序(46.953125秒)>二分查找插入排序(23.296875秒)>希尔排序(0.46875秒)


可见,所谓“二分查找插入排序”比起普通“插入排序”效率提升了一半。

代码如下:
  1. Option Explicit
  2. Dim brr(), x&, gd
  3. Public Sub Sort14() '二分查找插入排序(稳定)
  4.     Dim t!, arr(), i&, j&, n&, rng_h&
  5.     t = Timer()
  6.     Sht.Activate
  7.     Range("i3:i" & Rows.Count).ClearContents
  8.     rng_h = Range("a" & Rows.Count).End(xlUp).Row
  9.     If rng_h < 3 Then
  10.         End
  11.     ElseIf rng_h = 3 Then
  12.         ReDim arr(1 To 1, 1 To 1)
  13.         arr(1, 1) = Range("a3").Value
  14.     Else
  15.         arr = Range("a3:a" & rng_h).Value
  16.     End If
  17.     n = UBound(arr, 1)
  18.     ReDim brr(1 To n)
  19.     For i = 1 To n
  20.         brr(i) = arr(i, 1)
  21.     Next i
  22.     If brr(1) > brr(2) Then gd = brr(1): brr(1) = brr(2): brr(2) = gd
  23.     For i = 3 To n
  24.         gd = brr(i) '储存当前拟插入值
  25.         x = i '储存当前拟插入值序号
  26.         If brr(i) < brr(i - 1) Then Call DG_efcz(1, i - 1)
  27.     Next i
  28.     For i = 1 To n
  29.         arr(i, 1) = brr(i)
  30.     Next i
  31.     Range("i3").Resize(n, 1).Value = arr
  32.     Range("i2").Value = Timer() - t
  33. End Sub
  34. Public Sub DG_efcz(l&, r&) '有序区数组左起点、右起点
  35.     Dim c1&, c2&, i&, j&
  36.     c1 = Int((l + r) / 2)
  37.     c2 = c1 + 1
  38.     If brr(x) >= brr(c1) And brr(x) < brr(c2) Then '若同时brr(x) <= brr(c2)的话则不稳定
  39.         For i = x - 1 To c2 Step -1
  40.             brr(i + 1) = brr(i)
  41.         Next i
  42.         brr(c2) = gd
  43.     ElseIf brr(x) < brr(c1) Then
  44.         If c1 = l Then
  45.             If brr(x) < brr(l) Then j = l Else j = l + 1
  46.             For i = x - 1 To j Step -1
  47.                 brr(i + 1) = brr(i)
  48.             Next i
  49.             brr(j) = gd
  50.         Else
  51.             Call DG_efcz(l, c1)
  52.         End If
  53.     ElseIf brr(x) >= brr(c2) Then
  54.         Call DG_efcz(c2, r)
  55.     End If
  56. End Sub
复制代码



同步更新1楼附件。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-10-4 07:57 | 显示全部楼层
表示对楼主的研究精神敬重心悠然而生,平时我也是把代码弄来用,把能弄懂的就修改成自己平时习惯去用,没弄懂就丢一边了,没这么详细去研究

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-10-4 19:54 | 显示全部楼层
aoe1981 发表于 2019-10-3 22:40
受您的启发,又做了一个“二分查找插入排序”,这个算法可以设计成稳定的,它像希尔一样,是对普通插入排 ...
  1. Sub pey_testb()
  2. Dim t1, t2
  3. t1 = Timer

  4. Dim arr, k0&, ar(), i&
  5. k0 = [a1].End(4).Row
  6. arr = [a1].Resize(k0, 1)

  7. ReDim ar(1 To k0)
  8. For i = 1 To k0
  9.     ar(i) = arr(i, 1)
  10. Next i

  11. t2 = Timer

  12. Dim br() As Long, dic As Object, j&, m&
  13. Set dic = CreateObject("Scripting.Dictionary")

  14. ReDim br(1 To k0)
  15. m = 1: br(m) = ar(m): dic(br(m)) = 1

  16. '''''''循环插入

  17. For i = 2 To k0
  18.    If Not dic.exists(ar(i)) Then
  19.       m = m + 1
  20.       For j = m To VL(ar(i), br, m) + 2 Step -1
  21.           br(j) = br(j - 1)
  22.       Next j
  23.       br(j) = ar(i)
  24.    End If
  25.    dic(ar(i)) = dic(ar(i)) + 1
  26. Next i

  27. [e9] = Timer() - t2
  28. '''''''''结果输出
  29. Dim brr(), n&
  30. ReDim brr(1 To k0, 1 To 1)

  31. For i = 1 To m
  32.    For j = 1 To dic(br(i))
  33.        n = n + 1: brr(n, 1) = br(i)
  34.    Next j
  35. Next i

  36. [f1].Resize(k0, 1) = brr
  37. [e11] = Timer() - t1
  38. End Sub

  39. Function VL(X, R, n)
  40.     l = 0: h = n
  41.    
  42.     Do
  43.        t = l + (h - l) \ 2
  44.       
  45.        If X < R(t) Then
  46.             If t = 1 Then VL = 0: Exit Do
  47.             h = t
  48.        Else
  49.             If t = h - 1 Then VL = t: Exit Do
  50.             l = t
  51.        End If
  52.     Loop
  53. End Function
复制代码
100万组数字 ,速度有所提升 约2秒

333.jpg

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-10-4 22:44 来自手机 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-10-4 23:25 | 显示全部楼层
zopey 发表于 2019-10-4 19:54
100万组数字 ,速度有所提升 约2秒

兄台电脑速度快啊,我试了20000整数,用了6.71875,7.0078125……不论硬件,还是软件,都是天外有天啊……

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-10-4 23:31 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
ychj526926 发表于 2019-10-4 22:44
二维数组排序 我觉得香川的快排最牛!

哈哈,香川的“二维数组”排序我没用过,不过“我也觉得”如此!

工作表自带排序相信已经是登峰造极的算法了,我有时候也有些冲动,想练习一下“二维数组”排序,但转念想到工作表排序中不同“关键字”的组合,有些升序,有些降序,不一而论,情况众多,想必更是在做无用功,且目前无用功已做的太多了,便又时时提醒自己打消念头,或者等到有更多闲暇时间后再说……哈哈
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

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

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

GMT+8, 2024-4-26 10:46 , Processed in 0.040887 second(s), 16 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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