算法4 vba二分法符号表

二分法实现的符号表

' 二分查找的符号表
' 隔离索引,从1开始,数组操作从0开始

' 这种设计隔离数组操作,只是为了方便理解,如果实际使用,可以修改为 从0开始,能节省不少操作。
Private keys()

Private values()


Private n As Long


' 暂时省略辅助的增加和缩减,如有需要,参照以前的博客
' 基本的符号表api


Private Sub class_initialize()
    ' 省略增加,适当加大
    ReDim keys(100)
    ReDim values(100)
End Sub

' 把值加入符号表中,如果值为空,就删除主键
Sub putValue(key As Variant, val As Variant)
    Dim index As Long
    
    Dim temp As Variant
    
    index = rank(key)
    
    Dim i As Long
    
    
    ' 需要考虑到相等的情况
    ' 终究是不太明白为什么index会大于n?哪种情况?
    If index <= n And index > 0 Then
        If getKeyByIndex(index) = key Then
            setValueByIndex index, val
            Exit Sub
        End If
    End If
    
    For i = n + 1 To index + 2 Step -1
        setKeyByIndex i, getKeyByIndex(i - 1)
        setValueByIndex i, getValueByIndex(i - 1)
    Next
    
    setKeyByIndex index + 1, key
    setValueByIndex index + 1, val
    
    n = n + 1
    
End Sub

' 为了索引和数量保持对应,隔离数组操作

Function less(i As Variant, j As Variant) As Boolean
    less = i < j
End Function

Function greator(i As Variant, j As Variant) As Boolean

    greator = i > j
End Function

Function getKeyByIndex(i As Long) As Variant
    getKeyByIndex = keys(i - 1)
End Function

Function getValueByIndex(i As Long) As Variant
    getValueByIndex = values(i - 1)
End Function

Sub setKeyByIndex(i As Long, key As Variant)
    keys(i - 1) = key
End Sub

Sub setValueByIndex(i As Long, value As Variant)
    values(i - 1) = value
End Sub

' 获取键的值,如果键为空,就返回空

Function getValue(key As Variant) As Variant
    Dim index As Long
    
    If isEmpty() Then getValue = Null: Exit Function
    
    index = rank(key)
    
    If index <= n Then
        If getKeyByIndex(index) = key Then
            getValue = getValueByIndex(index)
            Exit Function
        End If
    End If
    
    getValue = Null
    
End Function

' 从表中删除主键
Sub delete(key As Variant)
    Dim index As Long
    
    
End Sub

' 主键是否存在于符号表中
Function contains(key As Variant) As Boolean
    Dim index As Long
    
    index = rank(key)
    
    If index <= n Then
    
        If getKeyByIndex(index) = key Then contains = True: Exit Function
    
    End If
    contains = False
End Function

' 是否为空
Function isEmpty() As Boolean
    isEmpty = n = 0
End Function

' 最小的主键
Function min() As Variant
    min = getKeyByIndex(1)
End Function


' 最大的主键
Function max() As Variant
    max = getKeyByIndex(n)
End Function

' 小于等于key的最大键
Function floor(key As Variant) As Variant
    Dim index As Long
    
    index = rank(key)
    
    floor = getKeyByIndex(index)

End Function

' 大于等于key的最小键
Function ceiling(key As Variant) As Variant
    Dim index As Long
    
    index = rank(key)
    
    ceiling = getKeyByIndex(index + 1)
End Function

' 小于key的数量
Function rank(key As Variant) As Long
    Dim low As Long
    Dim high As Long
    
    low = 1
    
    high = n
    
    rank = doRank(key, low, high)
End Function

' 实施二分查找,这种方式更加直观
Private Function doRank(key As Variant, low As Long, high As Long) As Long
    Dim mid As Long
    
    Dim midKey As Variant
    ' high比low小,说明没有匹配的结果,只能选择合适的结果返回?high还是low是合适结果?
    ' 主要看返回,这里是以1为开始索引,所以返回的位置,刚好是等于或者小于key的最大值的个数,
    ' 当high < low 的时候,说明数组开始越界,有可能是high越界,也有可能是low越界,
    ' 这取决于上层是大于还是小于key。
    ' 如果上层是比key更大,即less(key,midKey)成立,准确位置就是low,
    ' 而因为比key大,所以需要-1才是比key小的位置,位置和个数是对应的。取low-1,即high
    ' 如果上层比key小,即greator(key,midKey)成立,准确位置就是high,
    ' 而因为比key小,所以这个位置刚好就是需要返回的位置,即个数,包括0。
    ' 而如果索引是从0开始,返回的是个数,也从0开始,返回偏大的索引刚好就是个数,因为索引+1 = 个数
    ' high + 1 = low ,所以返回low
    If high < low Then doRank = high: Exit Function
    ' 中间位置划分偏向左边,即左边更多
    mid = Int((high + low) / 2)
    
    midKey = getKeyByIndex(mid)
    
    If less(key, midKey) Then
        doRank = doRank(key, low, mid - 1)
        Exit Function
    ElseIf greator(key, midKey) Then
        doRank = doRank(key, mid + 1, high)
        Exit Function
    End If
    
    doRank = mid

End Function

' 排名为key的键
Function find(k As Long) As Variant
    find = getKeyByIndex(k)
End Function

' 删除最小的键
Sub deleteMin()

End Sub

' 删除最大的键
Sub deletMax()

End Sub

' 数量
Function size() As Integer
    size = n
End Function

' 键之间的数量
Function sizeRange(low As Variant, high As Variant)

End Function

' 键之间的所有主键
Function keysRange(low As Variant, high As Variant) As Collection

End Function

' 所有主键
Function keysAll() As Collection

End Function


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值