ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[原创] VBA内存二维数组对象的多key稳定排序算法

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2015-12-5 20:35 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖已被收录到知识树中,索引项:排序
搞什么呢?
把数据源用=int(rnd*10),看看什么效果吧!
还是先看我的程序,理解完再说吧。
要稳定,简单的很,增加一个Key,按原来序号再排一次。或者干脆用稳定的快速排序作为基础排序。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-12-5 21:24 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
Zamyi 发表于 2015-12-5 20:35
搞什么呢?
把数据源用=int(rnd*10),看看什么效果吧!
还是先看我的程序,理解完再说吧。

【用稳定的快速排序作为基础排序】……你错了,快速排序并非【稳定性排序算法】。

我知道你早已写过二维数组多key排序代码(使用了快速排序基础算法)

但我不能确定你的代码是否能满足稳定多key排序的要求。(光看你的代码,应该是做不到的。)

…………
事实上,为了满足排序速度的要求,我使用的排序算法核心代码,也正是快速排序算法。
这一点并无差异。

新的附件中,测试代码test2,也确实使用了=Int(Rnd * 10) 来赋值。
排序结果确证是稳定的。

TA的精华主题

TA的得分主题

发表于 2015-12-5 21:34 | 显示全部楼层
香川群子 发表于 2015-12-5 21:24
【用稳定的快速排序作为基础排序】……你错了,快速排序并非【稳定性排序算法】。

我知道你早已写过二 ...

经典的快速排序是非稳定的,但快速排序可以实现稳定的,但需付出多用内存及速度作为代价。这一点很多人都读死教科书。有空写一个吧。

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-12-5 21:40 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
Zamyi 发表于 2015-12-5 21:34
经典的快速排序是非稳定的,但快速排序可以实现稳定的,但需付出多用内存及速度作为代价。这一点很多人都 ...

理论上,如果一个排序区间中相同内容值只有唯一的1个t(1组n个都是=t),那么以此t为检查比较值进行快速排序时,结果是稳定的……这是一个可以利用的特点。

TA的精华主题

TA的得分主题

发表于 2015-12-5 22:13 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
我没看代码,这个其实很好理解
比如有一张按学号序列的成绩表原始数据,现在要按照总成绩降序排序,分数相同的学号在前的排在前——一个简单的双关键字排序问题。
其实,这里要求 分数相同学号在前的排在前 换个高端的说法,就是要求按照分数进行稳定排序
所以处理稳定排序的方法也和处理这种要求的方法一样 把原来的序号加进去排就是了
伪代码:(VB6/VBA不支持Return语句,相当于FunctionName=XXX:Exit Function)(并且假设Key可以通过 “-” 运算进行大小比较)
Private Function Compare(entry1,entry2) As Integer
        '# 按Key1升序排列
        r= entry1.Key1-entry2.Key2
          If r<>0 Then Return r

        '# 按key2 降序排列
        r=entry1.Key1-entry2.Key2
        If r<>0 Then Return -r

        '…… ……

        '# 稳定 按Index排序
        r=entry1.Index-entry2.Index
        Return r
End Function

TA的精华主题

TA的得分主题

发表于 2015-12-6 09:02 | 显示全部楼层
学习一下,上次还到处找人求助去重,排序

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-12-6 11:32 | 显示全部楼层
PLINQ 发表于 2015-12-5 22:13
我没看代码,这个其实很好理解
比如有一张按学号序列的成绩表原始数据,现在要按照总成绩降序排序,分数相 ...

明白了。你说的对。

看来是我把问题搞复杂了。
根源是受工作表排序做法的影响。如果多key超过3,那么工作表排序需要改为单列倒序排序。

而事实上,无需倒序排序,任可按正常排序权重顺序排,只要最后进行稳定排序处理即可。
Zamyi 说的是对的。他的代码效率高多了。

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-12-6 15:30 | 显示全部楼层
本帖最后由 香川群子 于 2015-12-7 20:08 编辑

最后是按照Zamyi的方法重新写了代码。

多key排序时,按我原先的方法,每单次排序耗时查不了多少,
而按Zamyi和PLINQ的思路写的代码,第1次排序耗时最多,这以后的耗时将很快减少……因为多key重复(内容相同项将越来越少。)

TA的精华主题

TA的得分主题

发表于 2015-12-7 11:45 | 显示全部楼层
香川群子 发表于 2015-12-6 15:30
最后是按照Zamyi的方法重新写了代码。

还是需要老师帮忙:上了个附件
选取有效区域数据直接排序后输出,谢谢!

选取有效区域数据直接排序后输出.rar

2 MB, 下载次数: 105

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-12-8 16:02 | 显示全部楼层
qx-liuwx 发表于 2015-12-7 11:45
还是需要老师帮忙:上了个附件
选取有效区域数据直接排序后输出,谢谢!

按你附件的要求,用我的二维数组多key排序写了2个代码,比工作表排序大约快3倍。

方法-1、把cx列也列入排序。这样一共是4个key参与排序。
读取数据时,先要把第1列从文本型转为数值型。

排序参数:
sr = Array(102, 2, 103, 2, 1, 2, 2, 1)……102列cx降序、103列cy降序、第1列降序、第2列升序。
nr = szpx1(ar, 2, sr)……此处2代表前面2行不参与排序,从第3行开始。

过程中,第一次cx排序后,忽略后面空值继续。
最后输出有效结果955行。

………………

方法-2、先读取cx列中有效行对应3列写入数组,这样一共只要3个key参与排序。
读取数据时,也要把第1列从文本型转为数值型。

排序参数:
sr = Array(1, 2, 2, 2, 3, 1)……第1列cy列降序、第2列a列降序、第3列b列升序。
nr = szpx2(ar, 0, k - 1, sr)……行范围从0,k-1 (k为有效cx列行数)
最后输出有效结果955行。

…………
结果是,第2种方法速度更快一些。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-17 16:29 , Processed in 0.048423 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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