C#のスタックを試してみた
スタックは、オブジェクト(データ)を後入れ後出しするコレクションです。
目次
Stackクラス
非ジェネリックのStackクラスとジェネリックの Stackクラス がありますが、ここではStackクラスを使います。
スタック特有のプロパティやメソッドがいくつかあります。
Push()メソッド
スタックにオブジェクトを積む(スタックにオブジェクトを追加する)メソッドです。
void Push(item);
パラメータ |
型 |
内容 |
---|---|---|
item |
T |
スタックに追加するオブジェクト |
Tはスタックの型です。
戻り値はありません。
Pop()メソッド
スタックの一番上に積まれたオブジェクト(スタックに最後に追加したオブジェクト)を返すメソッドです。
Peekと違って、返したオブジェクトはスタックから削除されます。
スタックの一番上のオブジェクトを「取り出す」というイメージです。
引数はありません。
戻り値の型はスタックの型です。(stringのスタックなら、戻り値の型はstring。)
Peek()メソッド
スタックの一番上に積まれたオブジェクト(スタックに最後に追加したオブジェクト)を返すメソッドです。
Popと違って、Peekはスタック自体には変更を加えません。
スタックの一番上のオブジェクトを「見る」というイメージです。
引数はありません。
戻り値の型はスタックの型です。(stringのスタックなら、戻り値の型はstring。)
Countプロパティ
スタック内のオブジェクトの数を取得するint型のプロパティです。
Clear()メソッド
スタック内の全てのオブジェクトを削除します。
戻り値はありません。
試してみた
スタックを使ってハノイの塔的なプログラムを作ってみました。といっても、スタックを塔に見立てただけで、ハノイの塔自体を解くプログラムではありません。
3つの塔をそれぞれスタックにして、段の取り出しをPopで、段を積むのをPushで行うというものです。
ビュー
テキストブロックとボタンをグリッドに並べました。
<Window x:Class="stack_trial.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:stack_trial"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="40" />
<RowDefinition Height="1*" />
<RowDefinition Height="40" />
<RowDefinition Height="40" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<TextBlock Name="textblockNotification" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="3" HorizontalAlignment="Center" VerticalAlignment="Center" />
<TextBlock Name="textblockTemp" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="3" HorizontalAlignment="Center" VerticalAlignment="Center" />
<TextBlock Name="textblockLeft" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Bottom" FontFamily="Consolas" />
<TextBlock Name="textblockCenter" Grid.Column="1" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Bottom" FontFamily="Consolas" />
<TextBlock Name="textblockRight" Grid.Column="2" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Bottom" FontFamily="Consolas" />
<Button Name="buttonPushLeft" Content="Push" Grid.Column="0" Grid.Row="3" Margin="5" Click="buttonPushLeft_Click" />
<Button Name="buttonPopLeft" Content="Pop" Grid.Column="0" Grid.Row="4" Margin="5" Click="buttonPopLeft_Click" />
<Button Name="buttonPeekLeft" Content="Peek" Grid.Column="0" Grid.Row="5" Margin="5" Click="buttonPeekLeft_Click" />
<Button Name="buttonPushCenter" Content="Push" Grid.Column="1" Grid.Row="3" Margin="5" Click="buttonPushCenter_Click" />
<Button Name="buttonPopCenter" Content="Pop" Grid.Column="1" Grid.Row="4" Margin="5" Click="buttonPopCenter_Click" />
<Button Name="buttonPeekCenter" Content="Peek" Grid.Column="1" Grid.Row="5" Margin="5" Click="buttonPeekCenter_Click" />
<Button Name="buttonPushRight" Content="Push" Grid.Column="2" Grid.Row="3" Margin="5" Click="buttonPushRight_Click" />
<Button Name="buttonPopRight" Content="Pop" Grid.Column="2" Grid.Row="4" Margin="5" Click="buttonPopRight_Click" />
<Button Name="buttonPeekRight" Content="Reek" Grid.Column="2" Grid.Row="5" Margin="5" Click="buttonPeekRight_Click" />
</Grid>
</Window>
コード
スタックにPush、またはスタックからPopしたら、その都度塔の表示を書き換えるというプログラムです。 コードは長いですが、プログラムとしては単純です。
using System.Collections.Generic;
using System.Linq;
using System.Windows;
namespace stack_trial
{
public partial class MainWindow : Window
{
// 各塔のスタックのインスタンス
Stack<string> LeftTower = new Stack<string>();
Stack<string> CenterTower = new Stack<string>();
Stack<string> RightTower = new Stack<string>();
public void flush_towers()
{
// 塔を表示し直す
string[] tower = LeftTower.ToArray<string>(); // スタックを配列に変換
textblockLeft.Text = string.Empty;
foreach(string s in tower)
{
textblockLeft.Text = textblockLeft.Text + s + "\r\n"; // 配列から塔の外観を作る
}
textblockCenter.Text = string.Empty;
tower = CenterTower.ToArray<string>();
foreach(string s in tower)
{
textblockCenter.Text = textblockCenter.Text + s + "\r\n";
}
textblockRight.Text = string.Empty;
tower = RightTower.ToArray<string>();
foreach (string s in tower)
{
textblockRight.Text = textblockRight.Text + s + "\r\n";
}
}
public MainWindow()
{
InitializeComponent();
// 左の塔を積む
LeftTower.Push("*******");
LeftTower.Push(" ***** ");
LeftTower.Push(" *** ");
LeftTower.Push(" * ");
textblockTemp.Text = string.Empty;
flush_towers();
}
private void buttonPeekLeft_Click(object sender, RoutedEventArgs e)
{
if (LeftTower.Count < 1) return; // スタックに何も積まれていない場合は、何もしない
string str = LeftTower.Peek(); // スタックの一番上を取り出す(スタックには何もしない)
textblockNotification.Text = "左の一番上: " + str;
}
private void buttonPeekCenter_Click(object sender, RoutedEventArgs e)
{
if (CenterTower.Count < 1) return;
string str = CenterTower.Peek();
textblockNotification.Text = "中央の一番上: " + str;
}
private void buttonPeekRight_Click(object sender, RoutedEventArgs e)
{
if (RightTower.Count < 1) return;
string str = RightTower.Peek();
textblockNotification.Text = "右の一番上: " + str;
}
private void buttonPopLeft_Click(object sender, RoutedEventArgs e)
{
if (textblockTemp.Text.Length > 0) return; // 段を移動中は何もしない
if (LeftTower.Count < 1) return; // スタックに何も積まれていない場合は、何もしない
textblockTemp.Text = LeftTower.Pop(); // スタックの一番上を取り出す(スタックから一番上が消える)
flush_towers();
}
private void buttonPopCenter_Click(object sender, RoutedEventArgs e)
{
if (textblockTemp.Text.Length > 0) return;
if (CenterTower.Count < 1) return;
textblockTemp.Text = CenterTower.Pop();
flush_towers();
}
private void buttonPopRight_Click(object sender, RoutedEventArgs e)
{
if (textblockTemp.Text.Length > 0) return;
if (RightTower.Count < 1) return;
textblockTemp.Text = RightTower.Pop();
flush_towers();
}
private void buttonPushLeft_Click(object sender, RoutedEventArgs e)
{
if (textblockTemp.Text.Length < 1) return; // 段を移動中でなければ、何もしない
LeftTower.Push(textblockTemp.Text); // スタックに移動中の段を積む
textblockTemp.Text = string.Empty;
flush_towers();
}
private void buttonPushCenter_Click(object sender, RoutedEventArgs e)
{
if (textblockTemp.Text.Length < 1) return;
CenterTower.Push(textblockTemp.Text);
textblockTemp.Text = string.Empty;
flush_towers();
}
private void buttonPushRight_Click(object sender, RoutedEventArgs e)
{
if (textblockTemp.Text.Length < 1) return;
RightTower.Push(textblockTemp.Text);
textblockTemp.Text = string.Empty;
flush_towers();
}
}
}
動かしてみた
起動してみます。
左側に積まれています。
Peekを押すと一番上の段が表示されます。
PopとPushをいろいろ操作して、解いてみました。
ハノイの塔の解き方については ウィキペディア を参照してください。
公開日
広告
C#でデータ処理カテゴリの投稿
- C#でDataAdapterを使ってAccessのデータベースを読み書きしてみた
- C#でDataAdapterを使ってAccessのデータベースを読み書きしてみた(OleDb編)
- C#でDataGridに表示するデータを操作してみた
- C#でDataTableのカラムのデータ型を読んでみた
- C#でDataTableの自動インクリメントをしてみた
- C#でJSON形式のデータを出力してみた
- C#でLinq to objectの結果をDataTableにしてみた
- C#でSQLite3のデータベースを使ってみる(ADO.NET ファクトリーデザインパターン)
- C#でSQLiteを使ってみる(インストール)
- C#でコレクションの要素の数を調べる
- C#でコレクションを内部結合してみた
- C#でコレクションを左外部結合してみた
- C#でコレクションを昇順または降順に並び替える
- C#で渡された配列を加工して配列で返す関数について注意すること
- C#のキューを試してみた
- C#のスタックを試してみた