找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 3766|回复: 3

【VB】调用JDK源码中的红黑树实现高效插入删除查询

[复制链接]

9

主题

10

回帖

451

积分

用户组: 中·技术宅

UID
5181
精华
3
威望
39 点
宅币
260 个
贡献
79 次
宅之契约
0 份
在线时间
42 小时
注册时间
2019-7-25
发表于 2020-11-8 19:51:46 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
本帖最后由 天马座 于 2020-11-15 01:11 编辑

VB自带容器没有查找树并且字典也不是高效的实现,所以本人想给VB造个轮子
那么当然要选择红黑树了,因为红黑树实现比较复杂(本人抄代码都抄3小时,连复制再粘贴)
所以本人直接把JDK TreeMap源码移植到vb了,好处是JDK的实现相对来说比较可靠
红黑树的核心代码就是插入和删除,其他所有操作接口跟普通二叉搜索树完全一样
本人对vb编辑器不太熟悉,用它打字慢,所以直接用按键编辑器写成vbs版本了,大家简单修改一下就变成vb了
下面代码vb和vbs版本区别就是变量没有定义类型,还有就是Entry类中的成员名left,right vb无法定义得改名,用记事本批量替换一下就可以 其他一样,后续我有时间上网会同步更新完善

2020年11月13日更新完善了所有接口 并且添加VB6版本的代码生成器 在附件下载
全部写完之后测试效率有点低,原因是用类写的节点,Set语句会频繁COM的AddRef,QueryInterface,Release
如果想要高效的实现请改为数组版用6个数组模拟RBEntry 参考 https://www.0xaa55.com/thread-26178-1-1.html

  1. Class RBEntry
  2.     Public key
  3.     Public value
  4.     Public parent
  5.     Public leftChild
  6.     Public rightChild
  7.     Public color
  8. End Class
  9. Class KVPair
  10.     Public key
  11.     Public value
  12. End Class
  13. Class BasicCompare
  14.     Public Function compare(ByVal a, ByVal b)
  15.         If a < b Then
  16.             compare = - 1
  17.         ElseIf b < a Then
  18.             compare = 1
  19.         Else
  20.             compare = 0
  21.         End If
  22.     End Function
  23. End Class
  24. Class BasicEqual
  25.     Public Function equal(ByVal a, ByVal b)
  26.         If a = b Then
  27.             equal = true
  28.         Else
  29.             equal = false
  30.         End If
  31.     End Function
  32. End Class
  33. Class TreeMap
  34.     Private RED, BLACK
  35.     Private root
  36.     Private size
  37.     Private a
  38.     Private keyCpr
  39.     Private valueCpr
  40.     Private Sub Class_Initialize()
  41.         RED   = false
  42.         BLACK = true
  43.         Set root = Nothing
  44.         Set keyCpr = New BasicCompare
  45.         Set valueCpr = New BasicEqual
  46.         size = 0
  47.     End Sub
  48.     Private Sub Class_Terminate()
  49.         Call clear()
  50.     End Sub
  51.     Private Function newEntry(ByRef key, ByRef value, ByVal parent)
  52.         Dim o
  53.         Set o = New RBEntry
  54.         Call setKey(o,key)
  55.         Call setValue(o,value)
  56.         Set o.parent = parent
  57.         Set o.leftChild = Nothing
  58.         Set o.rightChild = Nothing
  59.         o.color = BLACK
  60.         Set newEntry = o
  61.     End Function
  62.     Public Function clone()
  63.         Dim o
  64.         Set o = New TreeMap
  65.         o.setKeyCompare keyCpr
  66.         o.setValueCompare valueCpr
  67.         Dim p
  68.         Set p = getFirstEntry()
  69.         Do While Not (p Is Nothing)
  70.             o.add p.key, p.value
  71.             Set p = successor(p)
  72.         Loop
  73.         Set clone = o
  74.     End Function
  75.     Public Sub setKeyCompare(ByVal newCpr)
  76.         If newCpr Is Nothing Then Exit Sub
  77.         Set keyCpr = newCpr
  78.         Call clear()
  79.     End Sub
  80.     Public Sub setValueCompare(ByVal newCpr)
  81.         If newCpr Is Nothing Then Exit Sub
  82.         Set valueCpr = newCpr
  83.         Call clear()
  84.     End Sub
  85.     Public Property Get count()
  86.             count = size
  87.     End Property
  88.     Public Function isEmpty()
  89.         isEmpty = (size = 0)
  90.     End Function
  91.     Public Function newEnum()
  92.         If size = 0 Then
  93.             newEnum = array()
  94.             Exit Function
  95.         End If
  96.         ReDim a(size-1)
  97.         Dim p
  98.         Dim i
  99.         i = 0
  100.         Set p = getFirstEntry()
  101.         Do While Not (p Is Nothing)
  102.             Set a(i) = New KVPair
  103.             Call setKey(a(i), p.key)
  104.             Call setValue(a(i), p.value)
  105.             Set p=successor(p)
  106.             i = i + 1
  107.         Loop
  108.         newEnum = a
  109.         Erase a
  110.     End Function
  111.     Public Sub clear()
  112.         Call unlink(root)
  113.         Set root = Nothing
  114.         size = 0
  115.     End Sub
  116.     Public Function getValue(ByVal key)   
  117.             Dim p
  118.             Set p = getEntry(key)
  119.             If p Is Nothing Then
  120.                 Exit Function
  121.             End If
  122.             If VarType(p.value) = vbObject Then
  123.             Set getValue = p.value
  124.         Else
  125.             getValue = p.value
  126.         End If
  127.     End Function
  128.     Public Sub add(ByVal key, ByVal value)
  129.         Dim t
  130.         Set t = root
  131.         If t Is Nothing Then
  132.             Set root = newEntry(key, value, Nothing)
  133.             size = 1
  134.             Exit Sub
  135.         End If
  136.         Dim parent
  137.         Dim cmp
  138.         Do
  139.             Set parent = t
  140.             cmp = keyCpr.compare(key, t.key)
  141.             If cmp < 0 Then
  142.                 Set t = t.leftChild
  143.             ElseIf cmp > 0 Then
  144.                 Set t = t.rightChild
  145.             Else
  146.                 Call setValue(t,value)
  147.                 Exit Sub
  148.             End If
  149.         Loop While Not(t Is Nothing)
  150.         Set e = newEntry(key, value, parent)
  151.         If cmp < 0 Then
  152.             Set parent.leftChild = e
  153.         Else
  154.             Set parent.rightChild = e
  155.         End If
  156.         Call fixAfterInsertion(e)
  157.         size = size + 1
  158.     End Sub
  159.     Public Sub remove(ByVal key)
  160.         Dim p
  161.         Set p = getEntry(key)
  162.         If p Is Nothing Then
  163.             Exit Sub
  164.         End If
  165.         Call deleteEntry(p)
  166.     End Sub
  167.     Private Sub fixAfterInsertion(ByVal x)
  168.         Dim y
  169.         x.color = RED
  170.         Do While Not (x Is Nothing)  And Not (x Is root)
  171.             If x.parent.color <> RED Then
  172.                 Exit Do
  173.             End If
  174.             If parentOf(x) Is leftChildOf(parentOf(parentOf(x))) Then
  175.                 Set y = rightChildOf(parentOf(parentOf(x)))
  176.                 If colorOf(y) = RED Then
  177.                     Call setColor(parentOf(x), BLACK)
  178.                     Call setColor(y, BLACK)
  179.                     Call setColor(parentOf(parentOf(x)), RED)
  180.                     Set x = parentOf(parentOf(x))
  181.                 Else
  182.                     If x Is rightChildOf(parentOf(x)) Then
  183.                         Set x = parentOf(x)
  184.                         Call rotateLeft(x)
  185.                     End If
  186.                     Call setColor(parentOf(x), BLACK)
  187.                     Call setColor(parentOf(parentOf(x)), RED)
  188.                     Call rotateRight(parentOf(parentOf(x)))
  189.                 End If
  190.             Else
  191.                 Set y = leftChildOf(parentOf(parentOf(x)))
  192.                 If colorOf(y) = RED Then
  193.                     Call setColor(parentOf(x), BLACK)
  194.                     Call setColor(y, BLACK)
  195.                     Call setColor(parentOf(parentOf(x)), RED)
  196.                     Set x = parentOf(parentOf(x))
  197.                 Else
  198.                     If x Is leftChildOf(parentOf(x)) Then
  199.                         Set x = parentOf(x)
  200.                         Call rotateRight(x)
  201.                     End If
  202.                     Call setColor(parentOf(x), BLACK)
  203.                     Call setColor(parentOf(parentOf(x)), RED)
  204.                     Call rotateLeft(parentOf(parentOf(x)))
  205.                 End If
  206.             End If
  207.         Loop
  208.         root.color = BLACK
  209.     End Sub
  210.     Private Sub deleteEntry(ByVal p)
  211.         size = size - 1
  212.         Dim replacement
  213.         If Not (p.leftChild Is Nothing)  And Not (p.rightChild Is Nothing)  Then
  214.             Dim s
  215.             Set s = successor(p)
  216.             Call setKey(p,s.key)
  217.             Call setValue(p,s.value)
  218.             Set p = s
  219.         End If
  220.         If Not (p.leftChild Is Nothing)  Then
  221.             Set replacement = p.leftChild
  222.         Else
  223.             Set replacement = p.rightChild
  224.         End If
  225.         If Not (replacement Is Nothing)  Then
  226.             Set replacement.parent = p.parent
  227.             If p.parent Is Nothing Then
  228.                 Set root = replacement
  229.             ElseIf p Is p.parent.leftChild Then
  230.                 Set p.parent.leftChild  = replacement
  231.             Else
  232.                 Set p.parent.rightChild = replacement
  233.             End If
  234.             Set p.parent = Nothing
  235.             Set p.rightChild = Nothing
  236.             Set p.leftChild = Nothing
  237.             If p.color = BLACK Then
  238.                 Call fixAfterDeletion(replacement)
  239.             End If
  240.         ElseIf p.parent Is Nothing Then
  241.             Set root = Nothing
  242.         Else
  243.             If p.color = BLACK Then
  244.                 Call fixAfterDeletion(p)
  245.             End If
  246.             If Not (p.parent Is Nothing)  Then
  247.                 If p Is p.parent.leftChild Then
  248.                     Set p.parent.leftChild = Nothing
  249.                 ElseIf p Is p.parent.rightChild Then
  250.                     Set p.parent.rightChild = Nothing
  251.                 End If
  252.                 Set p.parent = Nothing
  253.             End If
  254.         End If
  255.     End Sub
  256.     Private Sub fixAfterDeletion(ByVal x)
  257.         Dim sib
  258.         Do While Not (x Is root)  And colorOf(x) = BLACK
  259.             If x Is leftChildOf(parentOf(x)) Then
  260.                 Set sib = rightChildOf(parentOf(x))
  261.                 If colorOf(sib) = RED Then
  262.                     Call setColor(sib, BLACK)
  263.                     Call setColor(parentOf(x), RED)
  264.                     Call rotateLeft(parentOf(x))
  265.                     Set sib = rightChildOf(parentOf(x))
  266.                 End If
  267.                 If colorOf(leftChildOf(sib)) = BLACK And colorOf(rightChildOf(sib)) = BLACK Then
  268.                     Call setColor(sib, RED)
  269.                     Set x = parentOf(x)
  270.                 Else
  271.                     If colorOf(rightChildOf(sib)) = BLACK Then
  272.                         Call setColor(leftChildOf(sib), BLACK)
  273.                         Call setColor(sib, RED)
  274.                         Call rotateRight(sib)
  275.                         Set sib = rightChildOf(parentOf(x))
  276.                     End If
  277.                     Call setColor(sib, colorOf(parentOf(x)))
  278.                     Call setColor(parentOf(x), BLACK)
  279.                     Call setColor(rightChildOf(sib), BLACK)
  280.                     Call rotateLeft(parentOf(x))
  281.                     Set x = root
  282.                 End If
  283.             Else
  284.                 Set sib = leftChildOf(parentOf(x))
  285.                 If colorOf(sib) = RED Then
  286.                     Call setColor(sib, BLACK)
  287.                     Call setColor(parentOf(x), RED)
  288.                     Call rotateRight(parentOf(x))
  289.                     Set sib = leftChildOf(parentOf(x))
  290.                 End If
  291.                 If colorOf(rightChildOf(sib)) = BLACK And colorOf(leftChildOf(sib)) = BLACK Then
  292.                     Call setColor(sib, RED)
  293.                     Set x = parentOf(x)
  294.                 Else
  295.                     If colorOf(leftChildOf(sib)) = BLACK Then
  296.                         Call setColor(rightChildOf(sib), BLACK)
  297.                         Call setColor(sib, RED)
  298.                         Call rotateLeft(sib)
  299.                         Set sib = leftChildOf(parentOf(x))
  300.                     End If
  301.                     Call setColor(sib, colorOf(parentOf(x)))
  302.                     Call setColor(parentOf(x), BLACK)
  303.                     Call setColor(leftChildOf(sib), BLACK)
  304.                     Call rotateRight(parentOf(x))
  305.                     Set x = root
  306.                 End If
  307.             End If
  308.         Loop
  309.         Call setColor(x, BLACK)
  310.     End Sub
  311.     Private Sub rotateLeft(ByVal p)
  312.         Dim r
  313.         if Not (p Is Nothing) Then
  314.             Set r = p.rightChild
  315.             Set p.rightChild = r.leftChild
  316.             If Not (r.leftChild Is Nothing)  Then
  317.                 Set r.leftChild.parent = p
  318.             End If
  319.             Set r.parent = p.parent
  320.             If p.parent Is Nothing Then
  321.                 Set root = r
  322.             ElseIf p.parent.leftChild Is p Then
  323.                 Set p.parent.leftChild = r
  324.             Else
  325.                 Set p.parent.rightChild = r
  326.             End If
  327.             Set r.leftChild = p
  328.             Set p.parent = r
  329.         End If
  330.     End Sub
  331.     Private Sub rotateRight(ByVal p)
  332.         Dim l
  333.         If Not (p Is Nothing)  Then
  334.             Set l = p.leftChild
  335.             Set p.leftChild = l.rightChild
  336.             If Not (l.rightChild Is Nothing)  Then
  337.                 Set l.rightChild.parent = p
  338.             End If
  339.             Set l.parent = p.parent
  340.             If p.parent Is Nothing Then
  341.                 Set root = l
  342.             ElseIf p.parent.rightChild Is p Then
  343.                 Set p.parent.rightChild = l
  344.             Else
  345.                 Set p.parent.leftChild = l
  346.             End If
  347.             Set l.rightChild = p
  348.             Set p.parent = l
  349.         End If
  350.     End Sub
  351.     Private Sub setKey(ByVal p,ByRef key)
  352.         If VarType(key) = vbObject Then
  353.             Set p.key = key
  354.         Else
  355.             p.key = key
  356.         End If
  357.     End Sub
  358.     Private Sub setValue(ByVal p,ByRef value)
  359.         If VarType(value) = vbObject Then
  360.             Set p.value = value
  361.         Else
  362.             p.value = value
  363.         End If
  364.     End Sub
  365.     Private Sub setColor(ByVal p, ByVal c)
  366.         If Not (p Is Nothing)  Then
  367.             p.color = c
  368.         End If
  369.     End Sub
  370.     Private Function colorOf(ByVal p)
  371.         If p Is Nothing Then
  372.             colorOf = BLACK
  373.         Else
  374.             colorOf = p.color
  375.         End If
  376.     End Function
  377.     Private Function parentOf(ByVal p)
  378.         If p Is Nothing Then
  379.             Set parentOf = Nothing
  380.         Else
  381.             Set parentOf = p.parent
  382.         End If
  383.     End Function
  384.     Private Function leftChildOf(ByVal p)
  385.         If p Is Nothing Then
  386.             Set leftChildOf = Nothing
  387.         Else
  388.             Set leftChildOf = p.leftChild
  389.         End If
  390.     End Function
  391.     Private Function rightChildOf(ByVal p)
  392.         If p Is Nothing Then
  393.             Set rightChildOf = Nothing
  394.         Else
  395.             Set rightChildOf = p.rightChild
  396.         End If
  397.     End Function
  398.     '二叉树操作函数
  399.     Public Function containsKey(ByVal key)
  400.         containsKey = Not (getEntry(key) Is Nothing)
  401.     End Function
  402.     Public Function containsValue(ByVal value)
  403.         Dim p
  404.         Set p = getFirstEntry()
  405.         Do While Not (p Is Nothing)
  406.             If valueCpr.equal(value,p.value) Then
  407.                 containsValue = true
  408.                 Exit Function
  409.             End If
  410.             Set p = successor(p)
  411.         Loop
  412.         containsValue = false
  413.     End Function
  414.     Public Function firstKey()
  415.         Dim p
  416.         Set p = getFirstEntry()
  417.         If p Is Nothing Then
  418.             Exit Function
  419.         End If
  420.         If VarType(p.key) = vbObject Then
  421.             Set firstKey = p.key
  422.         Else
  423.             firstKey = p.key
  424.         End If
  425.     End Function
  426.     Public Function lastKey()
  427.         Dim p
  428.         Set p = getLastEntry()
  429.         If p Is Nothing Then
  430.             Exit Function
  431.         End If
  432.         If VarType(p.key) = vbObject Then
  433.             Set lastKey = p.key
  434.         Else
  435.             lastKey = p.key
  436.         End If
  437.     End Function
  438.     Public Function higherKey(ByVal key)
  439.         Dim p
  440.         Set p = getHigherEntry(key)
  441.         If p Is Nothing Then
  442.             Exit Function
  443.         End If
  444.         If VarType(p.key) = vbObject Then
  445.             Set higherKey = p.key
  446.         Else
  447.             higherKey = p.key
  448.         End If
  449.     End Function
  450.     Public Function lowerKey(ByVal key)
  451.         Dim p
  452.         Set p = getLowerEntry(key)
  453.         If p Is Nothing Then
  454.             Exit Function
  455.         End If
  456.         If VarType(p.key) = vbObject Then
  457.             Set lowerKey = p.key
  458.         Else
  459.             lowerKey = p.key
  460.         End If
  461.     End Function
  462.     Public Function ceilingKey(ByVal key)
  463.         Dim p
  464.         Set p = getCeilingEntry(key)
  465.         If p Is Nothing Then
  466.             Exit Function
  467.         End If
  468.         If VarType(p.key) = vbObject Then
  469.             Set ceilingKey = p.key
  470.         Else
  471.             ceilingKey = p.key
  472.         End If
  473.     End Function
  474.     Public Function floorKey(ByVal key)
  475.         Dim p
  476.         Set p = getFloorEntry(key)
  477.         If p Is Nothing Then
  478.             Exit Function
  479.         End If
  480.         If VarType(p.key) = vbObject Then
  481.             Set floorKey = p.key
  482.         Else
  483.             floorKey = p.key
  484.         End If
  485.     End Function
  486.     Public Function selectKey(ByVal index)
  487.         Dim p
  488.         Set p = selectEntry(index)
  489.         If p Is Nothing Then
  490.             Exit Function
  491.         End If
  492.         If VarType(p.key) = vbObject Then
  493.             Set selectKey = p.key
  494.         Else
  495.             selectKey = p.key
  496.         End If
  497.     End Function
  498.     Public Function indexOf(ByVal key)
  499.         Dim p
  500.         Dim i
  501.         Set p = getFirstEntry()
  502.         i = 0
  503.         Do While not (p Is Nothing)
  504.             If keyCpr.compare(key,p.key) = 0 Then
  505.                 indexOf = i
  506.                 Exit Function
  507.             End If
  508.             Set p = successor(p)
  509.             i = i + 1
  510.         Loop
  511.         indexOf = - 1
  512.     End Function
  513.     Private Function getEntry(ByRef key)
  514.         Dim p
  515.         Dim cmp
  516.         Set p = root
  517.         Do While not (p Is Nothing)
  518.             cmp = keyCpr.compare(key,p.key)
  519.             If cmp < 0 Then
  520.                 Set p = p.leftChild
  521.             ElseIf cmp > 0 Then
  522.                 Set p = p.rightChild
  523.             Else
  524.                 Set getEntry = p
  525.                 Exit Function
  526.             End If
  527.         Loop
  528.         Set getEntry = Nothing
  529.     End Function
  530.     Private Function successor(ByVal t)
  531.         Dim p, ch
  532.         If t Is Nothing Then
  533.             Set successor = Nothing
  534.         ElseIf not (t.rightChild Is Nothing)  Then
  535.             Set p = t.rightChild
  536.             Do While not (p.leftChild Is Nothing)
  537.                 Set p = p.leftChild
  538.             Loop
  539.             Set successor = p
  540.         Else
  541.             Set p = t.parent
  542.             Set ch = t
  543.             Do While not (p Is Nothing)
  544.                 If Not (ch Is p.rightChild) Then Exit do
  545.                 Set ch = p
  546.                 Set p = p.parent
  547.             Loop
  548.             Set successor = p
  549.         End If
  550.     End Function
  551.     Private Function predecessor(ByVal t)
  552.         Dim p, ch
  553.         If t Is Nothing Then
  554.             Set predecessor = Nothing
  555.         ElseIf not (t.leftChild Is Nothing)  Then
  556.             Set p = t.leftChild
  557.             Do While not (p.rightChild Is Nothing)
  558.                 Set p = p.rightChild
  559.             Loop
  560.             Set predecessor = p
  561.         Else
  562.             Set p = t.parent
  563.             Set ch = t
  564.             Do While not (p Is Nothing)
  565.                 If Not (ch Is p.leftChild) Then Exit do
  566.                 Set ch = p
  567.                 Set p = p.parent
  568.             Loop
  569.             Set predecessor = p
  570.         End If
  571.     End Function
  572.     Private Function getFirstEntry()
  573.         Dim p
  574.         Set p = root
  575.         If Not (p Is Nothing)  Then
  576.             Do While Not (p.leftChild Is Nothing)
  577.                 Set p = p.leftChild  
  578.             Loop
  579.         End If
  580.         Set getFirstEntry = p
  581.     End Function
  582.     Private Function getLastEntry()
  583.         Dim p
  584.         Set p = root
  585.         If Not (p Is Nothing)  Then
  586.             Do While Not (p.rightChild Is Nothing)
  587.                 Set p = p.rightChild
  588.             Loop
  589.         End If
  590.         Set getLastEntry = p
  591.     End Function
  592.     Private Function getHigherEntry(ByRef key)
  593.         Dim cmp
  594.         Dim p, parent, ch
  595.         Set p = root
  596.         Do While Not (p Is Nothing)
  597.             cmp = keyCpr.compare(key, p.key)
  598.             If cmp < 0 Then
  599.                 If Not (p.leftChild Is Nothing)  Then
  600.                     Set p = p.leftChild
  601.                 Else
  602.                     Set getHigherEntry = p
  603.                     Exit Function
  604.                 End If
  605.             Else
  606.                 If Not (p.rightChild Is Nothing)  Then
  607.                     Set p = p.rightChild
  608.                 Else
  609.                     Set parent = p.parent
  610.                     Set ch = p
  611.                     Do While Not (parent Is Nothing)
  612.                         If Not (ch Is parent.rightChild) Then Exit Do
  613.                         Set ch = parent
  614.                         Set parent = parent.parent
  615.                     Loop
  616.                     Set getHigherEntry = parent
  617.                     Exit Function
  618.                 End If
  619.             End If
  620.         Loop
  621.         Set getHigherEntry = Nothing
  622.     End Function
  623.     Private Function getLowerEntry(ByRef key)
  624.         Dim cmp
  625.         Dim p, parent, ch
  626.         Set p = root
  627.         Do While Not (p Is Nothing)
  628.             cmp = keyCpr.compare(key, p.key)
  629.             If cmp > 0 Then
  630.                 If Not (p.rightChild Is Nothing)  Then
  631.                     Set p = p.rightChild
  632.                 Else
  633.                     Set getLowerEntry = p
  634.                     Exit Function
  635.                 End If
  636.             Else
  637.                 If Not (p.leftChild  Is Nothing)  Then
  638.                     Set p = p.leftChild
  639.                 Else
  640.                     Set parent = p.parent
  641.                     Set ch = p
  642.                     Do While Not (parent Is Nothing)
  643.                         If Not (ch Is parent.leftChild) Then Exit Do
  644.                         Set ch = parent
  645.                         Set parent = parent.parent
  646.                     Loop
  647.                     Set getLowerEntry = parent
  648.                     Exit Function
  649.                 End If
  650.             End If
  651.         Loop
  652.         Set getLowerEntry = Nothing
  653.     End Function
  654.     Private Function getCeilingEntry(ByRef key)
  655.         Dim cmp
  656.         Dim p, parent, ch
  657.         Set p = root
  658.         Do While Not (p Is Nothing)
  659.             cmp = keyCpr.compare(key, p.key)
  660.             If cmp < 0 Then
  661.                 If not (p.leftChild Is Nothing)  Then
  662.                     Set p = p.leftChild
  663.                 Else
  664.                     Set getCeilingEntry = p
  665.                     Exit Function
  666.                 End If
  667.             ElseIf cmp > 0 Then
  668.                 If not (p.rightChild Is Nothing)  Then
  669.                     Set p = p.rightChild
  670.                 Else
  671.                     Set parent = p.parent
  672.                     Set ch = p
  673.                     Do While Not (parent Is Nothing)
  674.                         If Not (ch Is parent.rightChild) Then Exit Do
  675.                         Set ch = parent
  676.                         Set parent = parent.parent
  677.                     Loop
  678.                     Set getCeilingEntry = parent
  679.                     Exit Function
  680.                 End If
  681.             Else
  682.                 Set getCeilingEntry = p
  683.                 Exit Function
  684.             End If
  685.         Loop
  686.         Set getCeilingEntry = Nothing
  687.     End Function
  688.     Private Function getFloorEntry(ByRef key)
  689.         Dim cmp
  690.         Dim p, parent, ch
  691.         Set p = root
  692.         Do While Not (p Is Nothing)
  693.             cmp = keyCpr.compare(key, p.key)
  694.             If cmp > 0 Then
  695.                 If not (p.rightChild  Is Nothing)  Then
  696.                     Set p = p.rightChild
  697.                 Else
  698.                     Set getFloorEntry = p
  699.                     Exit Function
  700.                 End If
  701.             ElseIf cmp < 0 Then
  702.                 If not (p.leftChild Is Nothing)  Then
  703.                     Set p = p.leftChild
  704.                 Else
  705.                     Set parent = p.parent
  706.                     Set ch = p
  707.                     Do While Not (parent Is Nothing)
  708.                         If Not (ch Is parent.leftChild) Then Exit Do
  709.                         Set ch = parent
  710.                         Set parent = parent.parent
  711.                     Loop
  712.                     Set getFloorEntry = parent
  713.                     Exit Function
  714.                 End If
  715.             Else
  716.                 Set getFloorEntry = p
  717.                 Exit Function
  718.             End If
  719.         Loop
  720.         Set getFloorEntry = Nothing
  721.     End Function
  722.     Private Function selectEntry(ByVal index)
  723.         If index < 0 or index >= size Then
  724.             Set selectEntry = Nothing
  725.             Exit Function
  726.         End If
  727.         Dim p
  728.         dim i
  729.         If index < size \ 2 Then
  730.             i = 0
  731.             Set p = getFirstEntry()
  732.             Do While Not (p Is Nothing)
  733.                 If i = index Then
  734.                     Set selectEntry = p
  735.                     Exit Function
  736.                 End If
  737.                 Set p = successor(p)
  738.                 i = i + 1
  739.             Loop
  740.             Set selectEntry = Nothing
  741.         Else
  742.             i = size - 1
  743.             Set p = getLastEntry()
  744.             Do While Not (p Is Nothing)
  745.                 If i = index Then
  746.                     Set selectEntry = p
  747.                     Exit Function
  748.                 End If
  749.                 Set p = predecessor(p)
  750.                 i = i - 1
  751.             Loop
  752.             Set selectEntry = Nothing
  753.         End If
  754.     End Function
  755.     Private Sub unlink(ByVal p)
  756.         If p Is Nothing Then
  757.             Exit Sub
  758.         End If
  759.         Call unlink(p.leftChild)
  760.         Call unlink(p.rightChild)
  761.         Set p.parent = Nothing
  762.     End Sub
  763. End Class
  764. '测试
  765. Set o = New TreeMap'创建一个红黑树
  766. 'o.setKeyCompare keyCpr 设置key比较器 这里注释掉 使用默认比较器
  767. 'o.setValueCompare valueEQ 设置value比较器 这里注释掉 使用默认比较器
  768. For i = 10 To 0 Step - 1 '插入11个键值对 key value
  769.     o.add i, i
  770. Next
  771. key = 5
  772. value = 5
  773. i = 5
  774. WScript.Echo o.isEmpty'判断树是否为空
  775. WScript.Echo o.count'获取键值对数量
  776. WScript.Echo o.containsKey(key)'判断key是否存在
  777. WScript.Echo o.containsValue(value)'判断key是否存在
  778. WScript.Echo o.getValue(key)'key对应的value
  779. WScript.Echo o.higherKey(key)'刚好大于key的key
  780. WScript.Echo o.lowerKey(key)'刚好小于key的key
  781. WScript.Echo o.ceilingKey(key)'刚好大于等于key的key
  782. WScript.Echo o.floorKey(key)'刚好小于等于key的key
  783. WScript.Echo o.indexOf(key)'key的排名
  784. WScript.Echo o.selectKey(i)'排名i对应的key
  785. WScript.Echo o.firstKey '最小的key
  786. WScript.Echo o.lastKey '最大的key
  787. o.remove 6'删除key
  788. For Each x In o.newEnum'顺序遍历
  789.     WScript.Echo x.key & "=" & x.value
  790. Next
  791. o.clear '清空树
  792. WScript.Echo o.isEmpty'判断树是否为空
  793. Set oo = o.clone'克隆该对象
复制代码

TreeMapVB6代码生成器.rar

10.09 KB, 下载次数: 14

本帖被以下淘专辑推荐:

回复

使用道具 举报

1112

主题

1653

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
245
威望
744 点
宅币
24254 个
贡献
46222 次
宅之契约
0 份
在线时间
2298 小时
注册时间
2014-1-26
发表于 2020-11-8 20:46:40 | 显示全部楼层
这种要是改,会改成VB.NET比较合适
回复 赞! 靠!

使用道具 举报

9

主题

179

回帖

1万

积分

用户组: 真·技术宅

UID
4293
精华
6
威望
441 点
宅币
8683 个
贡献
850 次
宅之契约
0 份
在线时间
339 小时
注册时间
2018-9-19
发表于 2020-11-9 09:50:50 | 显示全部楼层
原来是VBS哦,不错不错,但是有个很严重的问题,那就是VBS是基于COM的计数引用机制,对象之间循环会导致无法被释放BUG。
改成VB.NET的话肯定不错,.NET是GC引用机制可以避免这个问题,至于Left和Right被关键字占用的问题,VB.NET可以用方括号解决:Public [Left] As XXX, [Right] As XXX。
回复 赞! 靠!

使用道具 举报

9

主题

10

回帖

451

积分

用户组: 中·技术宅

UID
5181
精华
3
威望
39 点
宅币
260 个
贡献
79 次
宅之契约
0 份
在线时间
42 小时
注册时间
2019-7-25
 楼主| 发表于 2020-11-9 10:40:05 | 显示全部楼层
系统消息 发表于 2020-11-9 09:50
原来是VBS哦,不错不错,但是有个很严重的问题,那就是VBS是基于COM的计数引用机制,对象之间循环会导致无 ...

可以释放,删除节点x 删除后x的引用计数为0,清空所有节点,需要写一个递归函数就可以
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-4-27 12:36 , Processed in 0.041074 second(s), 36 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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