C#のスタックを試してみた

スタックは、オブジェクト(データ)を後入れ後出しするコレクションです。

目次

  1. Stackクラス
    1. Push()メソッド
    2. Pop()メソッド
    3. Peek()メソッド
    4. Countプロパティ
    5. Clear()メソッド
  2. 試してみた
    1. ビュー
    2. コード
    3. 動かしてみた

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();
        }
    }
}

動かしてみた

起動してみます。

左側に積まれています。

実行1

Peekを押すと一番上の段が表示されます。

実行2

PopとPushをいろいろ操作して、解いてみました。

実行3

ハノイの塔の解き方については ウィキペディア を参照してください。

公開日

広告