Java
 Computer >> コンピューター >  >> プログラミング >> Java

Javaでスタックを使ってキュー(Queue)を実装する方法を解説

キューとスタックの基本

Queue(キュー)Collection インターフェースを継承したクラスで、FIFO(First-In-First-Out:先入れ先出し)方式による要素の挿入と削除をサポートします。一方、Stack(スタック)Vector クラスのサブクラスであり、LIFO(Last-In-First-Out:後入れ先出し)方式でオブジェクトを管理します。つまり、スタックの一番上に追加された最後の要素が、最初に取り出される要素になります。

この2つのデータ構造の性質は正反対ですが、スタックを2つ組み合わせることで、キューを実装することが可能です。以下では、その具体的な実装方法を紹介します。

実装の考え方

ポイントは次の通りです。

  • enqueue(挿入): 要素は常に1つ目のスタック(stack1)に push します。
  • dequeue(削除): 2つ目のスタック(stack2)が空の場合、stack1 の中身をすべて pop して stack2 に push し直します。これにより順序が反転し、先に入れた要素が stack2 の先頭に来ます。その後、stack2 から pop すれば FIFO の動作が実現できます。

サンプルコード

import java.util.*;

public class QueueUsingStackTest {

    private Stack<Integer> stack1 = new Stack<>();
    private Stack<Integer> stack2 = new Stack<>();

    // 要素を追加する(enqueue)
    public void enqueue(int element) {
        stack1.push(element);
        System.out.println(element + " inserted");
    }

    // 要素を取り出す(dequeue)
    public void dequeue() {
        if (stack2.isEmpty()) {
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        System.out.println(stack2.pop() + " removed");
    }

    public static void main(String args[]) {
        QueueUsingStackTest test = new QueueUsingStackTest();
        test.enqueue(10);
        test.enqueue(50);
        test.enqueue(100);
        test.dequeue();
    }
}

実行結果

10 inserted
50 inserted
100 inserted
10 removed

コードの解説

このプログラムでは、まず 1050100 の順に enqueue を呼び出しています。すべての要素は stack1 に積まれていくため、stack1 の内部状態は上から「100 → 50 → 10」となります。

続いて dequeue を呼び出すと、stack2 が空であるため、stack1 の全要素が stack2 へ移されます。この時点で stack2 の内部状態は上から「10 → 50 → 100」となり、最初に入れた 10 が先頭に位置します。そのため pop の結果として 10 removed が出力され、FIFO の挙動が正しく再現されていることがわかります。

計算量について

enqueue 操作は常に O(1) です。dequeue 操作は、stack2 が空の場合に限り O(n) の要素移動が発生しますが、各要素は最大でも1回しか移動しないため、償却計算量(amortized complexity)としては O(1) となります。この手法は、JavaのコレクションAPIだけではなく、アルゴリズムの面接や試験でも頻出のトピックなので、ぜひ理解しておきましょう。

  1. JavaのJToggleButton実装ガイド:ON/OFF切替ボタンの作り方を解説

    JToggleButtonとは JToggleButtonはAbstractButtonを拡張したクラスで、クリックするたびにONとOFFが切り替わるトグルボタンを実現するために使用されます。通常のボタンと異なり、押した状態を保持できるのが特徴です。 JToggleButtonの主な特徴 最初に押されたときは押し込まれた状態のままとなり、もう一度押してはじめて元の状態(押されていない状態)に戻ります。 ボタンが押されるたびにActionEventが発生します。 さらに、JToggleButtonはItemEventも発生させることができます。このイベントは、選択状態という概念を持つコンポー

  2. JavaのJWindowを使ってスプラッシュ画面を実装する方法

    JWindowは、デスクトップ上の任意の位置に表示できるコンテナです。JFrameと異なり、タイトルバーやウィンドウ管理ボタンなどの装飾要素を持ちません。JWindowは、唯一の子クラスとしてJRootPaneを含んでいます。そのcontentPaneが、JWindowに追加される子コンポーネントの親となります。JFrameと同様に、JWindowもトップレベルコンテナの一つであり、「装飾のない(undecorated)JFrame」と考えることができます。タイトルバーやウィンドウメニューといった機能は備えていません。この特性を活かすと、JWindowはスプラッシュ画面として利用できます。アプ