2011-02-02 100 views
5

Tôi đang tìm cách triển khai Lớp "Ngăn xếp" trong VBA cho Excel. Tôi muốn sử dụng cấu trúc Last In First Out. Có ai gặp vấn đề này trước đây không? Bạn có biết thư viện bên ngoài xử lý cấu trúc như Stack, Hastable, Vector ... (ngoài Bộ sưu tập Excel gốc vv ...)Thuật toán LIFO (Stack)/Lớp cho Excel VBA

Cảm ơn

Trả lời

7

Đây là lớp ngăn xếp rất đơn giản.

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 

thử nghiệm nó

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

+1

Chào mừng bạn đến stackoverflow! 1 để cung cấp một số mã và hiển thị cách đơn giản này có thể được. Một vài cảnh báo: 1) Sử dụng '=' để trả về một giá trị trong các thói quen 'Push' và 'Pop' của bạn sẽ thất bại khi các đối tượng liên quan vì cú pháp VBA 'Set' gây phiền nhiễu. Xem phần cuối của câu trả lời này: http://stackoverflow.com/questions/4716382/excel-select-case/4719706#4719706 2) Lưu ý rằng việc lập chỉ mục vào Bộ sưu tập là O (n) trong thời gian. Xem http://stackoverflow.com/questions/4827963/what-is-the-difference-between-the-time-complexity-of-these-two-ways-of-using-loo/4830157#4830157 – jtolle

1

Tôi không biết về bất kỳ thư viện VBA bên ngoài cho các công trình. Đối với stack thủ tục gọi của tôi, tôi chỉ sử dụng một mảng toàn cầu và con trỏ mảng với các phương thức Push và Pop.

1

Bruce McKinney cung cấp mã cho một Stack, Danh sách, và Vector trong cuốn sách này (đó là VB5(), nhưng điều đó có lẽ không quan trọng nhiều!):

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

(Nó ra khỏi in, nhưng bản đã qua sử dụng có giá rẻ)

Các mã nguồn dường như là có sẵn ở đây:.

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

(Cà veat - Tôi chưa bao giờ sử dụng bất kỳ mã nào của anh ấy, nhưng tôi biết anh ấy là một chuyên gia VB được đánh giá cao, lâu năm và cuốn sách của anh ấy đã được đưa vào MSDN trong một thời gian dài.)

Tôi chắc chắn cũng có nhiều triển khai khác nhau cho những thứ này trôi nổi trên Internet, nhưng tôi không biết liệu có bất kỳ một trong số chúng được sử dụng rộng rãi bởi bất kỳ ai trừ tác giả của chúng. Tất nhiên, không có công cụ nào khó viết mã của riêng bạn, cho rằng VBA hỗ trợ các mảng có thể định lại (hầu hết các cách tới một véc-tơ) và cung cấp lớp Bộ sưu tập tích hợp (hầu hết các cách để một danh sách). Câu trả lời của Charles William cho một chồng là về tất cả các thông tin bạn cần. Chỉ cần cung cấp trình bao bọc của riêng bạn xung quanh một mảng hoặc một Bộ sưu tập, nhưng mã bên trong có thể tương đối tầm thường.

Đối với một hashtable, MS Scripting Runtime bao gồm một lớp từ điển về cơ bản là một. Xem:

Hash Table/Associative Array in VBA

+1

Tôi phải chỉ ra rằng mã McKinney là không hoàn toàn "tầm thường". Ông cũng cung cấp các lớp học lặp cho bộ sưu tập của mình, vv – jtolle

+0

cảm ơn rất nhiều, sẽ có một cái nhìn đến nó – BlackLabrador

0

Bạn có thể sử dụng ngăn xếp lớp trong System.Collections, như bạn có thể sử dụng Queue và những người khác. Chỉ cần tìm kiếm vb.net stack cho tài liệu. Tôi đã không thử tất cả các phương pháp (ví dụ: Getenumerator - Tôi không biết làm thế nào để sử dụng một iterator, nếu có thể trong VBA). Sử dụng một chồng hoặc một hàng đợi cung cấp cho bạn một số lợi ích tốt đẹp, thường không dễ dàng như vậy trong VBA. Bạn có thể sử dụng

anArray = myStack.ToArray 

NGAY CẢ nếu ngăn xếp trống (Trả về mảng có kích thước từ 0 đến -1).

Sử dụng Đối tượng bộ sưu tập tùy chỉnh, nó hoạt động rất nhanh do tính đơn giản của nó và có thể dễ dàng được viết lại (ví dụ: chỉ xử lý chênh lệch được nhập mạnh mẽ). Bạn có thể muốn thực hiện kiểm tra cho ngăn xếp trống. Nếu bạn cố gắng sử dụng Pop trên một ngăn xếp trống, VBA sẽ không xử lý nó một cách duyên dáng, như tất cả các đối tượng null.Tôi thấy hợp lý hơn khi sử dụng:

If myStack.Count > 0 Then 

từ chức năng sử dụng ngăn xếp, thay vì nướng vào clsStack.Pop. Nếu bạn nướng nó vào lớp, một cuộc gọi đến Pop có thể trả lại một giá trị của loại đã chọn - tất nhiên bạn có thể sử dụng điều này để xử lý các giá trị rỗng, nhưng bạn nhận được nhiều đau buồn hơn theo cách đó.

Một ví dụ về sử dụng:

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 

Sử dụng một LIFO-stack có thể cực kỳ hữu ích!

Lớp 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