【VBA】スタックを実装する

概要

以前VBAでキューを実装しました。今回はVBAでスタックを実装してみます。

https://kazusa-pg.com/vba-queue/

スタックの概要

スタックとは、コンピュータプログラムで使われるデータ構造のひとつです。
最後に入れたデータが最初に取り出されるLIFO(Last In First Out)といわれるデータ構造になります。

スタックを使用すると、データを一番最後に追加したものから順に取り出すことができます。
スタックにデータを追加することを「プッシュ(Push)」、スタックからデータを取り出すことを「ポップ(Pop)」と呼びます。

例えば、数字のリストがあるとして、このリストをスタックとして使用することで
最後に追加された数字から順に取り出すことができます。

スタックの実装

クラスモジュールを使用して、スタックを実装します。下記の機能を実装してみます。

  • 動的配列を利用してスタックを実装する。
  • スタックにデータを入れるpushメソッドを実装する。
  • スタックからデータを取り出すpopメソッドを実装する。
  • スタック内のデータ数を取得するcountメソッドを実装する。
  • スタックの内容をVariant型の配列として返すgetContentsメソッドを実装する。
  • スタックにデータが無い時にpopを実行するとエラーをraiseする。エラーの番号は1001とする。

スタックのクラスモジュールは以下になります。

 1Option Explicit
 2
 3Private ary() As Variant   '配列をスタックとして利用
 4Private size As Long       'スタックの現在のサイズ
 5
 6Private Sub Class_Initialize()
 7  'コンストラクタ
 8  
 9  ReDim ary(0)
10  size = 0
11  
12End Sub
13Public Sub push(v As Variant)
14  'スタックの一番上にデータを追加する
15  
16  size = UBound(ary) + 1
17  ReDim Preserve ary(size)
18  
19  Dim vType As Long
20  vType = VarType(v)
21  
22  Select Case vType
23    'オブジェクト、データアクセスオブジェクト、ユーザー定義型は
24    'Set構文を利用する
25    Case vbObject
26      Set ary(size) = v
27    Case vbDataObject
28      Set ary(size) = v
29    Case vbUserDefinedType
30      Set ary(size) = v
31    Case Else
32      ary(size) = v
33  End Select
34  
35End Sub
36Public Function pop() As Variant
37  'スタックの一番上のデータを取り出す
38  
39  If size = 0 Then
40    'スタックにデータが存在しないときは、エラー番号1001をRaiseする
41    Err.Raise 1001, "Stack", "スタックにデータが存在しません"
42  End If
43  
44  Dim vType As Long
45  vType = VarType(ary(size))
46  
47  Select Case vType
48    'オブジェクト、データアクセスオブジェクト、ユーザー定義型は
49    'Set構文を利用する
50    Case vbObject
51      Set pop = ary(size)
52    Case vbDataObject
53      Set pop = ary(size)
54    Case vbUserDefinedType
55      Set pop = ary(size)
56    Case Else
57      pop = ary(size)
58  End Select
59  
60  size = size - 1
61  ReDim Preserve ary(size)
62  
63End Function
64Public Function count() As Long
65  'スタックのデータ数を返す
66  
67  count = size
68
69End Function
70Public Function getContents() As Variant
71  'スタックの内容を配列として返す
72  'インデックス1が一番下のデータ
73  
74  getContents = ary
75
76End Function

スタッククラスのテスト

スタッククラスをテストするコードは以下になります。

 1Option Explicit
 2Sub test_Stack()
 3
 4  Dim s As Stack
 5  Set s = New Stack
 6  
 7  s.push 1
 8  Dim c As Collection
 9  Set c = New Collection
10  c.Add "valueテスト", "keyテスト"
11  s.push c
12  s.push "a"
13
14  MsgBox "スタックのデータ数は" & s.count & "個です。"
15  
16  Dim ary() As Variant
17  ary = s.getContents
18  
19  MsgBox "スタックから取り出したデータは" & s.pop & "です。"
20  Dim returnC As Collection
21  Set returnC = s.pop
22  MsgBox "スタックから取り出したデータは" & returnC("keyテスト") & "です。"
23  MsgBox "スタックから取り出したデータは" & s.pop & "です。"
24  MsgBox "スタックから取り出したデータは" & s.pop & "です。"
25  
26  Set s = Nothing
27  
28End Sub
1  s.push 1
2  Dim c As Collection
3  Set c = New Collection
4  c.Add "valueテスト", "keyテスト"
5  s.push c
6  s.push "a"</pre>

1→collection(value=”valueテスト”,key=”keyテスト”)→”a”の順でスタックにデータを3個追加します。

1MsgBox "スタックのデータ数は" & s.count & "個です。"

Stackクラスのcountを実行すると、現在のスタックの個数を表示します。
先程データを3つ追加したので3個と表示されます。

1  Dim ary() As Variant
2  ary = s.getContents

getContentsを利用して、スタックの内容を配列に格納しています。

1  MsgBox "スタックから取り出したデータは" & s.pop & "です。"
2  Dim returnC As Collection
3  Set returnC = s.pop
4  MsgBox "スタックから取り出したデータは" & returnC("keyテスト") & "です。"
5  MsgBox "スタックから取り出したデータは" & s.pop & "です。"
6  MsgBox "スタックから取り出したデータは" & s.pop & "です。"

スタックからデータを取り出しています。 最後に追加したものから順々に取り出していきます。 “a”→collection(value=”valueテスト”,key=”keyテスト”)→1

collection型はMsgboxで直接表示できないので、一旦変数に代入し、キーを指定して値を表示しています。

スタックに値がない状態でpopを実行するとエラー番号は1001をraiseします。

GitHub

https://github.com/kazusapg/vba_stack

関連ページ