ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[分享] 死磕 Dictionary! 关于字典排序的 最终方案! 。。。

[复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-7-22 15:14 | 显示全部楼层
本帖最后由 山中老人 于 2020-7-22 15:40 编辑

2020-07-22 整理代码和注释,排序部分代码 的 可读性提高些!

DevelopDictionarydd2-22.rar

86.36 KB, 下载次数: 87

TA的精华主题

TA的得分主题

发表于 2020-7-22 17:46 | 显示全部楼层
是否 边插入边排序?

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-7-22 20:25 | 显示全部楼层
zopey 发表于 2020-7-22 17:46
是否 边插入边排序?




【插入法】比冒泡法速度快,但对逆向的数据,就是一个悲剧。
【快速排序法】,对顺序或逆序数据,都是个悲剧!
我只好自己写了个【二分法】先进行粗略排序。

目前的排序算法顺序:
      1、先用快速排序法,如果快速排序法掉坑里了,调用【插入法】。
      2、【插入法】检测数据量大,就先用【二分法】粗略排序(有限次数)。
      3、【二分法】每次排序前,先检查数据是否已经完成排序,已经完成就跳出去了!

代码:
Private Function InsertSort(Arr() As Long, Operator As Boolean, Optional ByVal low As Variant = Null, Optional ByVal high As Variant = Null) '插入算法
    Dim MinI As Long, MaxI As Long
    If VBA.IsNull(low) Then
        MinI = LBound(Arr)
    Else
        MinI = low
    End If
    If VBA.IsNull(high) Then
        MaxI = UBound(Arr)
    Else
        MaxI = high
    End If

    If MinI >= MaxI Then Exit Function '1个元素
    Dim i As Long
    i = MaxI - MinI
    If i > 100 Then '利用二分算法 粗略排序
        i = Int(i ^ (1 / 3)) '开3次方
        Call DichotomySort(Arr(), MinI, MaxI, Operator, i) '二分算法
    End If

    Dim Tmp As Long '临时变量
    Dim PreI As Long '插入指针
    For i = MinI + 1 To MaxI
        Tmp = Arr(i)
        PreI = i - 1
        Do While PreI >= MinI
            If Operator Then
                If Not SortCArr_(Arr(PreI)) < SortCArr_(Tmp) Then Exit Do
            Else
                If Not SortCArr_(Arr(PreI)) > SortCArr_(Tmp) Then Exit Do
            End If
            Arr(PreI + 1) = Arr(PreI) '数据右移
            PreI = PreI - 1 '指针左移
        Loop
        Arr(PreI + 1) = Tmp '插入
    Next i
End Function



Private Function DichotomySort(Arr() As Long, ByVal low As Long, ByVal high As Long, Operator As Boolean, Optional ByVal Depth As Long = 0) As Long '二分法排序(粗略排序)
    'Depth 深度计,<=0 退出
    If low >= high Then Exit Function
    If ScanSort(Arr, low, high, Operator) Then '检查排序
        Exit Function
    End If
    If (high - low) < 10 Then
        InsertSort Arr, Operator, low, high
        Exit Function
    End If
    On Error GoTo Err1
    Dim l As Long, h As Long, js As Long, LoopJs As Long, Str As String
    Do While True
        LoopJs = LoopJs + 1
        l = low
        h = high
        js = 0
        Do While l < h
            Str = "A"
            If Operator Then
                If Not SortCArr_(Arr(l)) < SortCArr_(Arr(h)) Then GoTo Loop1
            Else
                If Not SortCArr_(Arr(l)) > SortCArr_(Arr(h)) Then GoTo Loop1
            End If
            swap Arr, l, h
            js = js + 1
Loop1:
            l = l + 1
            h = h - 1
        Loop
        DichotomySort = l
        l = low
        Do While l < h And h <= high
            Str = "B"
            If Operator Then
                If Not SortCArr_(Arr(l)) < SortCArr_(Arr(h)) Then GoTo Loop2
            Else
                If Not SortCArr_(Arr(l)) > SortCArr_(Arr(h)) Then GoTo Loop2
            End If
            swap Arr, l, h
            js = js + 1
Loop2:
            l = l + 1
            h = h + 1
        Loop
        If js = 0 Then Exit Do
    Loop
    If high - low <= 2 Then Exit Function
    Depth = Depth - 1
    If Depth <= 0 Then Exit Function
    Call DichotomySort(Arr(), low, DichotomySort, Operator, Depth)
    Call DichotomySort(Arr(), DichotomySort + 1, high, Operator, Depth)
    Exit Function
Err1:
    Debug.Print LoopJs & " ERR:" & Err.Description
End Function

TA的精华主题

TA的得分主题

发表于 2020-7-23 10:25 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2020-7-23 10:49 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-7-23 13:51 | 显示全部楼层
本帖最后由 山中老人 于 2020-7-25 07:54 编辑

这里讲讲排序算法吧!
我用到的经典排序算法没啥可讲的,打家看看十大经典排序算法(动图演示)就好了!

我就讲讲比较特殊的地方:

1、【分组】 将相同的数据元素合并为一组,再进行排序。我是用的字典来实现的,实际效果非常好!大大降低后面排序的压力。同时还有一个好处,能保证【数据稳定】。
     【数据稳定】:相同数据再排序后能保持相对位置一致。例如: 先给班上学生按【成绩】排序,再按【性别】排序,最终结果 男生这部分成绩好的仍然保持在前,就称为【稳定】;否则,男生们的成绩顺序是乱的,就是【不稳定】。
      【数据稳定】在大多数场景,都是必要的。
2、【二分法】排序
     非常简单! 就是简单的将要排序的数据等分为前后两段。取两段交界处的中点,通过比较交换,让中点之前的元素都小于等于它,中点以后的元素都大于等于它。再分别对前后两段,分别进行【二分法】排序。如此:1分2 ,2分4 ,4分8。
     这种算法,效率并不高,也不能保持【数据稳定】。但对一些特殊的情况非常好,例如:数据已经进行过排序,无论是顺序、还是逆序。
     它也很适合,给【插入法】进行预排序,大大提高【插入法】的速度。

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-7-23 15:06 | 显示全部楼层
十大经典排序算法(动图演示)
https://www.cnblogs.com/onepixel/articles/7674659.html

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-7-24 06:35 | 显示全部楼层
本帖最后由 山中老人 于 2020-7-25 07:45 编辑

2020-07-24
没啥可更新的了,稍稍优化了点代码,增加了测试用属性.

Private Property Get MonitorSortArr(Arr() As Long) As Variant()
'监视排序数组。(实时监视排序每一步效果)
'用法:在要监视的函数内,右键【添加监视】将表达式“MonitorSortArr(Arr())”加入


实测:2百万的随机数,实际【排序算法执行】1秒多,但是【数据准备】生成2百万随机数据花费近2分钟;【分组】花了二十秒;【应用排序结果】花费了1分钟!


对各种类型、混乱程度的数据都能有较好的表现,这基本是算法优化到极限了吧!

DevelopDictionaryd-25.rar

87.47 KB, 下载次数: 23

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-7-31 05:38 | 显示全部楼层
修订了一个bug.

DevelopDictionaryd-26.rar

88.8 KB, 下载次数: 48

TA的精华主题

TA的得分主题

发表于 2020-7-31 09:46 | 显示全部楼层
谢谢楼主分享,菜鸟学习分享知识
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

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

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

GMT+8, 2024-6-17 09:31 , Processed in 0.043417 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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