スタックの基本操作とは?データ構造におけるプリミティブ操作を解説
スタックは「後入れ先出し」(LIFO:Last In First Out)と呼ばれる方式で動作するデータ構造です。最後に追加した要素が最初に取り出されるという特性を持ち、数式の評価、関数呼び出しの管理、再帰処理など、コンピュータサイエンスのさまざまな場面で活用されています。
本記事では、スタックが備える基本操作(プリミティブ操作)について詳しく解説し、実際にスタックADTを使ったサンプルコードも紹介します。
ADT(抽象データ型)とは
ADT(Abstract Data Type:抽象データ型)とは、「値の集合」と「その上に定義される操作のセット」によって振る舞いが決められる特殊なデータ型のことです。「抽象的(Abstract)」という言葉が使われる理由は、利用者はこれらのデータ型を使ってさまざまな操作を実行できる一方で、その操作が内部でどのように実装されているかは完全に隠されているためです。ADTはプリミティブなデータ型から構成されますが、操作のロジックそのものは外部からは見えないようになっています。
スタックADTの主な操作一覧
スタックADTには、以下のような基本操作(関数)が用意されています。
- isFull():スタックが満杯かどうかを判定する
- isEmpty():スタックが空かどうかを判定する
- push(x):要素xをスタックに追加(プッシュ)する
- pop():スタックの先頭から要素を1つ取り除く
- peek():スタックの最上位にある要素を参照する(削除はしない)
- size():スタック内に存在する要素の数を取得する
実装例(C++)
それでは、C++のstackコンテナを使った具体的なコード例を見てみましょう。
#include<iostream>
#include<stack>
using namespace std;
main(){
stack<int> stk;
if(stk.empty()){
cout << "Stack is empty" << endl;
} else {
cout << "Stack is not empty" << endl;
}
// スタックへ要素を挿入
stk.push(10);
stk.push(20);
stk.push(30);
stk.push(40);
stk.push(50);
cout << "Size of the stack: " << stk.size() << endl;
// 要素を取り出しながら表示
while(!stk.empty()) {
int item = stk.top(); // peek操作に相当
stk.pop();
cout << item << " ";
}
}
実行結果
Stack is empty Size of the stack: 5 50 40 30 20 10
コードの解説
このプログラムでは、まず空のスタックに対してempty()(isEmpty操作に相当)を呼び出し、スタックの状態を確認しています。次にpush()を使って10から50までの5つの整数を順番に追加し、size()で現在の要素数である「5」を出力します。
最後のwhileループでは、top()(peek操作に相当)で先頭要素を取得し、pop()でそれを取り除くことを繰り返しています。出力結果が「50 40 30 20 10」という順序になっていることから、最後に入れた要素が最初に取り出されるというLIFOの特性が確認できます。
-
データ構造における二分木の表現方法|配列と連結リストの違いを解説
コンピュータメモリ上での二分木の表現方法 ここでは、二分木をコンピュータのメモリ上でどのように表現するかについて解説します。表現方法には主に2種類あり、配列を使う方法と連結リスト(リンクリスト)を使う方法があります。 配列による表現 まず、次のような二分木を例に考えてみましょう。 配列による表現では、木の要素をレベル順(幅優先順)に走査しながら格納していきます。つまり、ノードを上のレベルから順番に保存する方式です。存在しない要素がある場合は、その位置を空白のまま残します。上記の木を配列で表現すると、次のようになります。 123456789101112131415 10516-81520
-
データ構造の償却時間計算量とは?償却解析の基礎と計算方法を解説
償却解析(Amortized Analysis)とは償却解析は、ごく一部の操作が非常に遅い一方で、頻繁に実行される大半の操作は高速であるような状況で用いられる分析手法です。データ構造の分野では、ハッシュテーブルや素集合データ構造(Disjoint Set/Union-Find)などの性能評価において重要な役割を果たします。例えばハッシュテーブルでは、探索の時間計算量はほとんどの場合 O(1) ですが、ときに O(n) の操作が発生することがあります。要素の検索や挿入は通常、定数時間で完了する処理です。しかし衝突(コリジョン)が発生した場合には、その解決のために O(n) の操作が必要になること