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

スタックの概要
スタックとは、コンピュータプログラムで使われるデータ構造のひとつです。
最後に入れたデータが最初に取り出されるLIFO(Last In First Out)といわれるデータ構造になります。
スタックを使用すると、データを一番最後に追加したものから順に取り出すことができます。
スタックにデータを追加することを「プッシュ(Push)」、スタックからデータを取り出すことを
「ポップ(Pop)」と呼びます。
例えば、数字のリストがあるとして、このリストをスタックとして使用することで
最後に追加された数字から順に取り出すことができます。
スタックの実装
クラスモジュールを使用して、スタックを実装します。下記の機能を実装してみます。
- 動的配列を利用してスタックを実装する。
- スタックにデータを入れるpushメソッドを実装する。
- スタックからデータを取り出すpopメソッドを実装する。
- スタック内のデータ数を取得するcountメソッドを実装する。
- スタックの内容をVariant型の配列として返すgetContentsメソッドを実装する。
- スタックにデータが無い時にpopを実行するとエラーをraiseする。エラーの番号は1001とする。
スタックのクラスモジュールは以下になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
Option Explicit Private ary() As Variant '配列をスタックとして利用 Private size As Long 'スタックの現在のサイズ Private Sub Class_Initialize() 'コンストラクタ ReDim ary(0) size = 0 End Sub Public Sub push(v As Variant) 'スタックの一番上にデータを追加する size = UBound(ary) + 1 ReDim Preserve ary(size) Dim vType As Long vType = VarType(v) Select Case vType 'オブジェクト、データアクセスオブジェクト、ユーザー定義型は 'Set構文を利用する Case vbObject Set ary(size) = v Case vbDataObject Set ary(size) = v Case vbUserDefinedType Set ary(size) = v Case Else ary(size) = v End Select End Sub Public Function pop() As Variant 'スタックの一番上のデータを取り出す If size = 0 Then 'スタックにデータが存在しないときは、エラー番号1001をRaiseする Err.Raise 1001, "Stack", "スタックにデータが存在しません" End If Dim vType As Long vType = VarType(ary(size)) Select Case vType 'オブジェクト、データアクセスオブジェクト、ユーザー定義型は 'Set構文を利用する Case vbObject Set pop = ary(size) Case vbDataObject Set pop = ary(size) Case vbUserDefinedType Set pop = ary(size) Case Else pop = ary(size) End Select size = size - 1 ReDim Preserve ary(size) End Function Public Function count() As Long 'スタックのデータ数を返す count = size End Function Public Function getContents() As Variant 'スタックの内容を配列として返す 'インデックス1が一番下のデータ getContents = ary End Function |
スタッククラスのテスト
スタッククラスをテストするコードは以下になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
Option Explicit Sub test_Stack() Dim s As Stack Set s = New Stack s.push 1 Dim c As Collection Set c = New Collection c.Add "valueテスト", "keyテスト" s.push c s.push "a" MsgBox "スタックのデータ数は" & s.count & "個です。" Dim ary() As Variant ary = s.getContents MsgBox "スタックから取り出したデータは" & s.pop & "です。" Dim returnC As Collection Set returnC = s.pop MsgBox "スタックから取り出したデータは" & returnC("keyテスト") & "です。" MsgBox "スタックから取り出したデータは" & s.pop & "です。" MsgBox "スタックから取り出したデータは" & s.pop & "です。" Set s = Nothing End Sub |
7 8 9 10 11 12 |
s.push 1 Dim c As Collection Set c = New Collection c.Add "valueテスト", "keyテスト" s.push c s.push "a" |
1→collection(value=”valueテスト”,key=”keyテスト”)→”a”の順でスタックにデータを3個追加します。
14 |
MsgBox "スタックのデータ数は" & s.count & "個です。" |
Stackクラスのcountを実行すると、現在のスタックの個数を表示します。
先程データを3つ追加したので3個と表示されます。
16 17 |
Dim ary() As Variant ary = s.getContents |
getContentsを利用して、スタックの内容を配列に格納しています。
19 20 21 22 23 24 |
MsgBox "スタックから取り出したデータは" & s.pop & "です。" Dim returnC As Collection Set returnC = s.pop MsgBox "スタックから取り出したデータは" & returnC("keyテスト") & "です。" MsgBox "スタックから取り出したデータは" & s.pop & "です。" MsgBox "スタックから取り出したデータは" & s.pop & "です。" |
スタックからデータを取り出しています。
最後に追加したものから順々に取り出していきます。
“a”→collection(value=”valueテスト”,key=”keyテスト”)→1
collection型はMsgboxで直接表示できないので、一旦変数に代入し、キーを指定して値を表示しています。
スタックに値がない状態でpopを実行するとエラー番号は1001をraiseします。
コメント