アルゴリズムとデータ構造
演習第 3 回
スタックとキュー

この演習では、 スタック(アルゴリズムC 第1巻 p.29) の操作方法について学び、そのプログラムを作成します。 キュー(アルゴリズムC 第1巻 p.34) については触れませんが、スタックを作ることができれば、 キューを作るのもそれほど難しいことではありません。

問題1印刷用 PostScript

(1) 以下の式を逆ポーランド記法で表しなさい。

  1. 1 + 2 * 3
  2. ( 1 + 2 ) * 3
  3. ( 1 + 2 ) * ( 3 + 4 )
  4. 1 + ( 2 + 3 ) * 4 + 5

(2) (1) の 4 で逆ポーランド記法で表したものを、 スタックを使って計算しなさい。 ただし、計算過程でのスタックの状態も書くこと。

(1) は 逆ポーランド記法(アルゴリズムC 第1巻 p.31) に変換する問題です。 逆ポーランド記法は他にも 「後置記法」 「RPN (Reverse Polish Notation)」 「IPN (Inverse Polish Notation)」 などと呼ばれます。逆ポーランド記法は日本語表記と似ています。 例えば、1 + 2 を逆ポーランド記法で表すと 1 2 + になります。これは日本語で 「1 と 2 を足す(+)」 と書いたときの語順と同じです。 逆ポーランド記法にすると括弧が不要になります。 人間様には読みにくいかもしれませんが、 コンピュータが処理をする場合にはとても都合が良い表記方法です。

(2) では、以下の図を参考にして書いてみてください。

スタックの使用例
問題2

逆ポーランド記法で表された式を、 スタックを使って計算するプログラムを作成しなさい。 また、以下の条件を満たすこと。

実行例:
% ./a.out
Input data by Reverse Polish Notation: 12+34+*
1 
1 2 
3 
3 3 
3 3 4 
3 7 
21 
Answer: 21

余裕のある人は、もう少しスタックっぽく表示 できるよう工夫しなさい。

スタックを配列で表現する場合、次の図のようになります。

スタックを配列で表現

処理の流れとしては、まず getchar() などの入力関数を使って 入力データを 1 文字読み込みます。そのデータが数字であれば、 整数型に変換してスタックにプッシュし、+-*/ などの 記号であれば、スタックから 2 回ポップして計算して、計算結果を またプッシュします。

スタックを作るには、以下のような関数が必要になります。

void push(int x);

スタックにデータ x をプッシュ(一番上に置く)する関数

int pop();

スタックからデータをポップ(一番上を取る)して、それを返す関数

int isempty();

スタックが空かどうかをチェックする関数。空なら 1、そうでないなら 0 を返す。

isempty() 関数は pop() 関数の中で使います。 ポップする前にスタックにデータが入っているかを調べる必要があるからです (空ならポップできない)。

まずはスタック操作のための関数を作成し、簡単なテストをしてみると良いでしょう。

int main(){
  push(1);
  push(2);
  printf("poped value is %d.\n", pop());
  printf("poped value is %d.\n", pop());
}

実行すると、このようになるのが正解です。

% ./a.out
poped value is 2.
poped value is 1.

また、次のような関数を作成すれば、プログラミングしやすくなるでしょう。

int dtoi(char c);

文字型としての数字を整数型に変換する関数 (例: '5'5

void print_stack();

スタックの中身を表示する関数

問題3

逆ポーランド記法で表された式をスタックを使って計算するプログラム を作成しなさい。ただし、スタックを作るのにはリストを用いること。 他の条件については、問題2と同じで良い。 また、必要であれば 演習第 2 回 で使用した関数を用いなさい。

実行例:
% ./a.out
Input data by Reverse Polish Notation: 12+34+*
1 
2 1 
3 
3 3 
4 3 3 
7 3 
21 
Answer: 21

問題2とは違い、リストを使ってスタックを表現します。

スタックを連結リストで表現

リストでのプッシュは、head の次にノードを挿入します。

連結リストでプッシュ

リストでのポップは、head の次のノードを削除します。

連結リストでポップ

また、リストを使うことによって、キューも同様に作ることができます。


Written by わかまつなおき