【VBScript】キューとスタックを実装する

昔作ったもの。
.NETのSystem.Collections.QueueとSystem.Collections.Stackを使えばいいのに、当時は知らなくてイチから実装したorz
一応それっぽく動きます。

# キュー

![image.png](https://qiita-image-store.s3.amazonaws.com/0/96507/8c880aa0-0ee8-994e-bf11-80dec1ea0f77.png)

## クラス

```vb:Queue.vbsclass
Option Explicit
Class Queue

	'プロパティ
	Private arrQueue()	'動的配列(Extensionメソッドにより拡張)
	Private strBuf
	Private intFirst	'先頭位置
	Private intLength	'キュー内のデータ数
	Private i

	'コンストラクタ
	Private Sub Class_Initialize

		ReDim arrQueue(10)
		intLength = 0
		intFirst = 0
		i = 0

	End Sub

	'デストラクタ
	Private Sub Class_Terminate
	End Sub

	'エンキュー
	Public Function Enqueue(strVal)

		arrQueue(i) = strVal
		intLength = intLength + 1
		i = i + 1

		'配列が5つ消費されると自動拡張
		If (i Mod 5) = 0 Then
			Extension
		End If

	End Function

	'デキュー
	Public Function Dequeue

		If (intLength -1) => 0 Then
			strBuf = arrQueue(intFirst)
			intFirst = intFirst + 1
			intLength = intLength -1
		Else
			strBuf = ""
		End If
		Dequeue = strBuf

	End Function

	'先頭要素を取得
	Public Function First

		strBuf = arrQueue(intFirst)
		First = strBuf

	End Function

	'末尾要素を取得
	Public Function Last

		strBuf = arrQueue(intFirst + intLength - 1)
		Last = strBuf

	End Function

	'キュー要素数取得
	Public Function GetLength

		GetLength = intLength

	End Function

	'配列拡張
	Private Function Extension

		'Preserveをつけると拡張後も配列の値が保存される。
		ReDim Preserve arrQueue(i + 10)

	End Function

End Class
```

## テスター

```vb:queueTester.wsf
<job>
<script language="vbscript" src="Queue.vbsclass"/>
<script language="vbscript">

Dim objQueue

Set objQueue = New Queue

objQueue.Enqueue("hoge")
objQueue.Enqueue("fuga")
objQueue.Enqueue(1)

WScript.StdOut.Write "先頭要素：" & objQueue.First & vbCrLf
WScript.StdOut.Write "末尾要素：" & objQueue.Last & vbCrLf
WScript.StdOut.Write "キューの長さ" & objQueue.GetLength & vbCrLf

WScript.StdOut.Write "デキュー：" & objQueue.Dequeue & vbCrLf
WScript.StdOut.Write "デキュー：" & objQueue.Dequeue & vbCrLf
WScript.StdOut.Write "デキュー：" & objQueue.Dequeue & vbCrLf
WScript.StdOut.Write "デキュー：" & objQueue.Dequeue & vbCrLf

Dim i
for i = 1 to 100
	objQueue.Enqueue(i)
next

WScript.StdOut.Write "先頭要素：" & objQueue.First & vbCrLf
WScript.StdOut.Write "末尾要素：" & objQueue.Last & vbCrLf
WScript.StdOut.Write "キューの長さ" & objQueue.GetLength & vbCrLf
WScript.StdOut.Write "デキュー：" & objQueue.Dequeue & vbCrLf

Set objQueue = Nothing

</script>
</job>
```

## 実行結果

```
>CScript /nologo queueTester.wsf
先頭要素：hoge
末尾要素：1
キューの長さ3
デキュー：hoge
デキュー：fuga
デキュー：1
デキュー：
先頭要素：1
末尾要素：100
キューの長さ100
デキュー：1
```

# スタック

![image.png](https://qiita-image-store.s3.amazonaws.com/0/96507/99c12c38-ecd9-48d8-d640-8ac5871dadc2.png)

## クラス

```vb:Stack.vbsclass
Option Explicit
Class Stack

	'プロパティ
	Private arrStack()	'動的配列(Extensionメソッドにより拡張)
	Private strBuf
	Private intStackPointer	'スタックポインタ

	'コンストラクタ
	Private Sub Class_Initialize

		ReDim arrStack(10)
		intStackPointer = 0

	End Sub

	'デストラクタ
	Private Sub Class_Terminate
	End Sub

	'プッシュ
	Public Function Push(strVal)

		arrStack(intStackPointer) = strVal
		intStackPointer = intStackPointer + 1

		'配列が5つ消費されると自動拡張
		If (intStackPointer Mod 5) = 0 Then
			Extension
		End If

	End Function

	'ポップ
	Public Function Pop

		If (intStackPointer - 1) < 0 Then
			strBuf = ""
		Else
			intStackPointer = intStackPointer - 1
			strBuf = arrStack(intStackPointer)
		End If
		Pop = strBuf

	End Function

	'ピーク
	Public Function Peek

		If (intStackPointer - 1) < 0 Then
			strBuf = ""
		Else
			strBuf = arrStack(intStackPointer - 1)
		End If
		Peek = strBuf

	End Function

	'スタックの深さ
	Public Function GetDepth

		GetDepth = intStackPointer

	End Function

	'配列拡張
	Private Function Extension

		'Preserveをつけると拡張後も配列の値が保存される。
		ReDim Preserve arrStack(intStackPointer + 10)

	End Function

End Class
```

## テスター

```vb:stackTester.wsf
<job>
<script language="vbscript" src="Stack.vbsclass"/>
<script language="vbscript">

Dim objStack

Set objStack = New Stack

objStack.Push("hoge")
objStack.Push("fuga")
objStack.Push(1)

WScript.StdOut.Write "トップ要素：" & objStack.Peek & vbCrLf
WScript.StdOut.Write "スタックの深さ" & objStack.GetDepth & vbCrLf

WScript.StdOut.Write "ポップ：" & objStack.Pop & vbCrLf
WScript.StdOut.Write "ポップ：" & objStack.Pop & vbCrLf
WScript.StdOut.Write "ポップ：" & objStack.Pop & vbCrLf
WScript.StdOut.Write "ポップ：" & objStack.Pop & vbCrLf

Dim i
for i = 1 to 100
	objStack.Push(i)
next
WScript.StdOut.Write "スタックの深さ" & objStack.GetDepth & vbCrLf
WScript.StdOut.Write "トップ要素：" & objStack.Peek & vbCrLf
WScript.StdOut.Write "ポップ：" & objStack.Pop & vbCrLf

Set objStack = Nothing

</script>
</job>
```

## 実行結果

```
>CScript /nologo stackTester.wsf
トップ要素：1
スタックの深さ3
ポップ：1
ポップ：fuga
ポップ：hoge
ポップ：
スタックの深さ100
トップ要素：100
ポップ：100
```