Excel VBA 的 LIFO(堆栈)算法/类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4871485/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 12:36:40  来源:igfitidea点击:

LIFO (Stack) Algorithm/Class for Excel VBA

excelvbastack

提问by BlackLabrador

I'm looking to implement a "Stack" Class in VBA for Excel. I want to use a Last In First Out structure. Does anyone came across this problem before ? Do you know external libraries handling structure such as Stack, Hastable, Vector... (apart the original Excel Collection etc...)

我希望在 VBA for Excel 中实现一个“堆栈”类。我想使用后进先出结构。有没有人遇到过这个问题?您是否知道外部库处理结构,例如 Stack、Hastable、Vector...(除了原始的 Excel Collection 等...)

Thanks

谢谢

回答by bruce

Here is a very simple stack class.

这是一个非常简单的堆栈类。

Option Explicit
Dim pStack As Collection
Public Function Pop() As Variant
    With pStack
        If .Count > 0 Then
            Pop = .Item(.Count)
            .Remove .Count
        End If
    End With
End Function
Public Function Push(newItem As Variant) As Variant
    With pStack
        .Add newItem
        Push = .Item(.Count)
    End With

End Function
Public Sub init()
    Set pStack = New Collection
End Sub

Test it

测试一下

Option Explicit
Sub test()
    Dim cs As New cStack
    Dim i As Long
    Set cs = New cStack
    With cs
        .init

        For i = 1 To 10
            Debug.Print CStr(.Push(i))
        Next i

        For i = 1 To 10
            Debug.Print CStr(.Pop)
        Next i
    End With
End Sub

Bruce

布鲁斯

回答by jtolle

Bruce McKinney provided code for a Stack, List, and Vector in this book (it was VB5(!), but that probably doesn't matter much):

Bruce McKinney 在本书中提供了 Stack、List 和 Vector 的代码(它是 VB5(!),但这可能无关紧要):

http://www.amazon.com/Hardcore-Visual-Basic-Bruce-McKinney/dp/1572314222

http://www.amazon.com/Hardcore-Visual-Basic-Bruce-McKinney/dp/1572314222

(It's out of print, but used copies are cheap.)

(它已经绝版了,但使用过的副本很便宜。)

The source code appears to be available here:

源代码似乎可以在这里找到:

http://vb.mvps.org/hardweb/mckinney2a.htm#2

http://vb.mvps.org/hardweb/mckinney2a.htm#2

(Caveat - I've never used any of his code, but I know he's a highly regarded, long-time VB expert, and his book was included on MSDN for a long time.)

(警告 - 我从未使用过他的任何代码,但我知道他是一位备受推崇的长期 VB 专家,并且他的书在 MSDN 上收录了很长时间。)

I'm sure there are also many different implementations for these things floating around the internet, but I don't know if any of them are widely used by anybody but their authors.

我敢肯定,这些东西在互联网上也有许多不同的实现,但我不知道其中是否有任何一个被除作者之外的任何人广泛使用。

Of course, none of this stuff is that hard to write your own code for, given that VBA supports resizeable arrays (most of the way to a vector) and provides a built-in Collection class (most of the way to a list). Charles William's answer for a stack is about all the info you need. Just provide your own wrapper around either an array or a Collection, but the code inside can be relatively trivial.

当然,考虑到 VBA 支持可调整大小的数组(大多数情况下是向量)并提供内置 Collection 类(大多数情况下是列表),因此编写自己的代码并不难。Charles William 对堆栈的回答是关于您需要的所有信息。只需为数组或集合提供您自己的包装器,但其中的代码可能相对简单。

For a hashtable, the MS Scripting Runtime includes a Dictionary class that basically is one. See:

对于哈希表,MS Scripting Runtime 包括一个基本上是一个的 Dictionary 类。看:

Hash Table/Associative Array in VBA

VBA中的哈希表/关联数组

回答by Charles Williams

I do not know of any external VBA libraries for these structures. For my procedure-call stack I just use a global array and array pointer with Push and Pop methods.

我不知道这些结构的任何外部 VBA 库。对于我的过程调用堆栈,我只使用具有 Push 和 Pop 方法的全局数组和数组指针。

回答by Espen Rosenquist

You can use the class Stack in System.Collections, as you can use Queue and others. Just search for vb.net stack for documentation. I have not tried all methods (e.g. Getenumerator - I don't know how to use an iterator, if at all possible in VBA). Using a stack or a queue gives you some nice benefits, normally not so easy in VBA. You can use

您可以在 System.Collections 中使用 Stack 类,就像使用 Queue 和其他类一样。只需在 vb.net 堆栈中搜索文档即可。我还没有尝试过所有方法(例如 Getenumerator - 我不知道如何使用迭代器,如果可能的话在 VBA 中)。使用堆栈或队列会给你带来一些好处,在 VBA 中通常不是那么容易。您可以使用

anArray = myStack.ToArray

EVEN if the stack is empty (Returns an array of size 0 to -1).

即使堆栈为空(返回大小为 0 到 -1 的数组)。

Using a custom Collections Object, it works very fast due to its simplicity and can easily be rewritten (e.g. to only handle strongly typed varibles). You might want to make a check for empty stack. If you try to use Pop on an empty stack, VBA will not handle it gracefully, as all null-objects. I found it more reasonable to use:

使用自定义的集合对象,由于其简单性,它的工作速度非常快,并且可以轻松重写(例如,仅处理强类型变量)。您可能想要检查空堆栈。如果您尝试在空堆栈上使用 Pop,VBA 将不会像所有空对象一样优雅地处理它。我发现使用更合理:

If myStack.Count > 0 Then

from the function using the stack, instead of baking it into clsStack.Pop. If you bake it into the class, a call to Pop can return a value of chosen type - of course you can use this to handle empty values, but you get much more grief that way.

从使用堆栈的函数中,而不是将其烘焙到 clsStack.Pop 中。如果你把它加入到类中,对 Pop 的调用可以返回一个选定类型的值——当然你可以用它来处理空值,但那样你会更加痛苦。

An example of use:

使用示例:

Private Sub TestStack()
    Dim i as long
    Dim myStack as clsStack

    Set myStack = New clsStack
    For i = 1 to 2
        myStack.Push i
    Next

    For i = 1 to 3
        If myStack.Count > 0 Then
            Debug.Print myStack.Pop
        Else
            Debug.Print "Stack is empty"
        End If
    Next

    Set myStack = Nothing
End Sub

Using a LIFO-stack can be extremely helpful!

使用 LIFO 堆栈非常有用!

Class clsStack

类 clsStack

Dim pStack as Object
Private Sub Class_Initialize()
    set pStack = CreateObject("System.Collections.Stack")
End Sub
Public Function Push(Value as Variant)
    pStack.Push Value
End Function
Public Function Pop() As Variant
    Pop = pStack.Pop
End Function
Public Function Count() as long
    Count = pstack.Count
End Function
Public Function ToArray() As Variant()
    ToArray = pStack.ToArray()
End Function
Public Function GetHashCode() As Integer
    GetHashCode = pStack.GetHashCode
End Function
Public Function Clear()
    pStack.Clear
End Function
Private Sub Class_terminate()
    If (Not pStack Is Nothing) Then
        pStack.Clear
    End If
    Set pStack = Nothing
End Sub