C++でキューを使用してスタックを実装する方法
キューでスタックを実装するとは
キューを使ってスタックを実装することを考えてみましょう。そのためには、スタックに対して以下のメソッドを定義する必要があります。
- push(x) – 要素xをスタックにプッシュします。
- pop() – スタックの先頭(トップ)要素を削除し、その値を返します。
- top() – スタックの先頭要素を参照して返します。
- empty() – スタックが空かどうかを判定して返します。
例えば、push(10)とpush(20)を順に呼び出した後、pop()を2回呼び出すと、出力は「20」「10」の順になります。これはスタックのLIFO(Last In First Out:後入れ先出し)という性質によるものです。
アルゴリズム(解き方の手順)
この問題を解くには、以下の手順に従います。
- デック(deque)q を1つ定義します。
- 関数 push(x) を定義し、x を q の先頭に挿入します。
- 関数 pop() を定義します。k := q の先頭要素とし、q から先頭要素を削除して k を返します。
- 関数 top() を定義します。q の先頭要素をそのまま返します。
- 関数 empty() を定義します。q が空の場合は true を、そうでなければ false を返します。
ポイントは、push時に先頭へ挿入(push_front)することです。これにより、最後に追加した要素が常に先頭に位置するため、キュー構造でありながらスタックと同じLIFOの動作を実現できます。
実装例
理解を深めるために、以下のC++実装を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
class MyStack {
private:
deque<int> q;
public:
void push(int x){
q.push_front(x);
}
int pop(){
int k = q.front();
q.pop_front();
return k;
}
int top(){
return q.front();
}
bool empty(){
if (q.empty())
return true;
else
return false;
}
};
main(){
MyStack ob;
ob.push(10);
ob.push(20);
cout << (ob.pop()) << endl;
cout << (ob.pop()) << endl;
}
入力
push(10),push(20),pop(),pop()
出力
20
10
計算量について
std::dequeでは先頭への挿入・削除・アクセスがすべてO(1)で行えるため、push・pop・top・emptyのどの操作も定数時間で実行できます。この実装はシンプルでありながら効率的で、面接や競技プログラミングでもよく使われるテクニックです。
-
C++でrand7()を使ってrand10()を実装する方法【棄却サンプリング】
問題概要 1から7までの一様なランダム整数を生成する関数 rand7() が与えられているとします。この関数を利用して、1から10までの一様なランダム整数を生成する関数 rand10() を実装するのが本記事の目的です。なお、乱数を直接生成するライブラリ関数を新たに使用することはできません。 解法のポイント:棄却サンプリング この問題を解く鍵は、rand7() を2回呼び出すことで、より広い範囲の一様分布を作り出すことです。 次の式を考えてみましょう。 rand40 = (rand7() - 1) * 7 + (rand7() - 1) これは7進法の2桁の数とみなすことができ、0から48
-
C++ STLのスタック(stack)徹底解説!LIFO構造の基本操作とサンプルコード
C++ STLにおけるスタック(stack)は、LIFO(Last In First Out:後入れ先出し)構造として実装されるコンテナです。LIFOとは「最後に入れたものが最初に取り出される」という意味で、本を一冊ずつ積み上げた山をイメージすると理解しやすいでしょう。一番上に置いた本(=最後に挿入された要素)が最初に取り出されることから、この構造はLIFOと呼ばれています。 スタックで使える主な操作 1. top() – 最上位要素の取得 スタックの最上位(先頭)にある要素への参照を返します。要素自体は削除されません。 構文:name_of_stack.top() 引数:なし 戻り値:ス