stack data structure c with illustration
基本的なhtmlとcssの面接の質問
C ++のスタックについて知っておくべきことすべて。
スタックは、要素を線形に格納するために使用される基本的なデータ構造です。
スタックが続きます LIFO(後入れ先出し) 操作が実行される順序またはアプローチ。これは、スタックに最後に追加された要素が、スタックから削除される最初の要素になることを意味します。
=> すべてのC ++トレーニングシリーズ全体を見るには、ここにアクセスしてください。
学習内容:
C ++でスタック
スタックは、実際のスタックまたは積み重ねたものの山に似ています。
以下に、Stackの図解を示します。

上に示したように、プレートの山が互いに積み重ねられています。別のアイテムを追加する場合は、上の図(左側)に示すように、スタックの一番上に追加します。アイテムをスタックに追加するこの操作は、「 押す 」。
右側では、反対の操作を示しています。つまり、スタックからアイテムを削除します。これも同じ端、つまりスタックの一番上から行われます。この操作は「 ポップ 」。
上図に示すように、プッシュとポップが同じ端から実行されていることがわかります。これにより、スタックはLIFOの順序に従います。アイテムがスタックに押し込まれたり、スタックからポップアウトされたりする位置または端は、「 スタックのトップ 」。
最初、スタックにアイテムがない場合、スタックの最上位は-1に設定されます。スタックにアイテムを追加すると、スタックの一番上が1ずつ増加し、アイテムが追加されたことを示します。これとは対照的に、アイテムがスタックからポップされると、スタックの一番上が1ずつ減少します。
次に、スタックの実装中に必要となるスタックデータ構造の基本的な操作のいくつかを確認します。
基本操作
以下は、スタックでサポートされている基本的な操作です。
- 押す - 要素をスタックに追加またはプッシュします。
- ポップ - スタックから要素を削除またはポップします。
- ピーク– スタックの最上位要素を取得しますが、削除しません。
- 一杯 - スタックがいっぱいかどうかをテストします。
- isEmpty – スタックが空かどうかをテストします。
図

上の図は、スタックで実行される一連の操作を示しています。最初は、スタックは空です。空のスタックの場合、スタックの最上位は-1に設定されます。
次に、要素10をスタックにプッシュします。スタックの最上位が要素10を指していることがわかります。
次に、要素20を使用して別のプッシュ操作を実行します。その結果、スタックの最上位が20を指します。この状態は3番目の図です。
最後の図では、pop()操作を実行しています。ポップ操作の結果、スタックの最上位を指す要素がスタックから削除されます。したがって、この図では、要素20がスタックから削除されていることがわかります。したがって、スタックの最上位は10を指します。
このようにして、スタックで使用されるLIFOアプローチを簡単に理解できます。
実装
#1)配列の使用
以下は、配列を使用したスタックのC ++実装です。
#include using namespace std; #define MAX 1000 //max size for stack class Stack { int top; public: int myStack(MAX); //stack array Stack() { top = -1; } bool push(int x); int pop(); bool isEmpty(); }; //pushes element on to the stack bool Stack::push(int item) { if (top >= (MAX-1)) { cout << 'Stack Overflow!!!'; return false; } else { myStack(++top) = item; cout< 出力:
スタックプッシュ
二
4
6
スタックポップ:
6
4
二
出力では、要素が1つの順序でスタックにプッシュされ、逆の順序でスタックからポップされていることがわかります。これは、スタックに対するLIFO(後入れ先出し)アプローチを示しています。
上記のスタックの配列実装では、ポインターが含まれていないため、これは非常に簡単に実装できると結論付けることができます。ただし、同時に、スタックのサイズは静的であり、スタックを動的に拡大または縮小することはできません。
次に、Javaプログラミング言語の配列を使用してスタックを実装します。
class Stack { static final int MAX = 1000; // Maximum Stack size int top; int myStack() = new int(MAX); boolean isEmpty() { return (top = (MAX-1)) { System.out.println('Stack Overflow'); return false; } else { myStack(++top) = item; System.out.println(item); return true; } } int pop() { if (top <0) { System.out.println('Stack Underflow'); return 0; } else { int item = myStack(top--); return item; } } } //Main class code class Main { public static void main(String args()) { Stack stack = new Stack(); System.out.println('Stack Push:'); stack.push(1); stack.push(3); stack.push(5); System.out.println('Stack Pop:'); while(!stack.isEmpty()) { System.out.println(stack.pop()); } } } 出力:
スタックプッシュ:
1
3
5
スタックポップ:
5
3
1
実装ロジックはC ++実装と同じです。出力は、要素をスタックにプッシュインおよびスタックからポップアウトするLIFO手法を示しています。
すでに述べたように、配列を使用したスタック実装は最も単純な実装ですが、スタックを動的に拡大または縮小できないため、静的な性質を持っています。
#2)リンクリストの使用
次に、C ++とJavaの両方でリンクリストを使用してスタック操作を実装します。最初に、C ++の実装を示します。
#include using namespace std; // class to represent a stack node class StackNode { public: int data; StackNode* next; }; StackNode* newNode(int data) { StackNode* stackNode = new StackNode(); stackNode->data = data; stackNode->next = NULL; return stackNode; } int isEmpty(StackNode *root) { return !root; } void push(StackNode** root, int new_data){ StackNode* stackNode = newNode(new_data); stackNode->next = *root; *root = stackNode; cout<data; free(temp); return popped; } int peek(StackNode* root) { if (isEmpty(root)) return -1; return root->data; } int main() { StackNode* root = NULL; cout<<'Stack Push:'< 出力:
スタックプッシュ:
100
200
300
一番上の要素は300です
スタックポップ:
300
200
.jsonファイルを表示する方法
100
一番上の要素は-1です
次に、リンクリストを使用したスタックのJava実装を示します。
class LinkedListStack { StackNode root; static class StackNode { int data; StackNode next; StackNode(int data) { this.data = data; } } public boolean isEmpty() { if (root == null) { return true; } else return false; } public void push(int new_data) { StackNode newNode = new StackNode(new_data); if (root == null) { root = newNode; } else { StackNode temp = root; root = newNode; newNode.next = temp; } System.out.println(new_data); } public int pop() { int popped = Integer.MIN_VALUE; if (root == null) { System.out.println('Stack is Empty'); } else { popped = root.data; root = root.next; } return popped; } public int peek() { if (root == null) { System.out.println('Stack is empty'); return Integer.MIN_VALUE; } else { return root.data; } } } class Main{ public static void main(String() args) { LinkedListStack stack = new LinkedListStack(); System.out.println('Stack Push:'); stack.push(100); stack.push(200); stack.push(300); System.out.println('Top element is ' + stack.peek()); System.out.println('Stack Pop:'); while(!stack.isEmpty()){ System.out.println(stack.pop()); } System.out.println('Top element is ' + stack.peek()); } } 出力:
スタックプッシュ:
100
200
300
一番上の要素は300です
スタックポップ:
300
200
100
スタックが空です
一番上の要素は-2147483648です
リンクリストを使用したスタックのC ++およびJavaの実装を見てきました。各スタックエントリをリンクリストのノードとして表します。この実装の最も重要な利点は、動的であるということです。これは、要件に応じてスタックサイズを拡大または縮小できることを意味します。
これは、事前にサイズを宣言する必要があり、動的にサイズを変更できない配列を使用したスタック実装の場合とは異なります。
この実装の欠点は、どこでもポインターを使用するため、配列の実装と比較すると、スペースを少し取りすぎることです。
スタックのアプリケーション
スタックデータ構造のアプリケーションのいくつかについて説明しましょう。スタックデータ構造は、主にその単純さと実装の容易さのために、ソフトウェアプログラミングのさまざまなアプリケーションで使用されます。
以下に、スタックのいくつかのアプリケーションについて簡単に説明します。
#1)接尾辞式への中置
一般的な算術式は次の形式になります オペランド1OPオペランド2 。
演算子OPの位置に基づいて、次のタイプの式があります。
- 中置 –中置式の一般的な形式は「 オペランド1OPオペランド2 」。これが表現の基本的な形であり、私たちは常に数学で使用しています。
- プレフィックス –演算子がオペランドの前に配置されている場合、それは接頭辞式です。中置式の一般的な形式は「 OPオペランド1オペランド2 」。
- Postfix –接尾辞式では、オペランドが最初に書き込まれ、次に演算子が書き込まれます。 「operand1operand2OP」の形式です。
「a + b * c」という式を考えてみましょう。 「」 。コンパイラーは、式を左から右または右から左にスキャンします。演算子の優先順位と結合性に注意して、最初に式をスキャンして式b * cを評価します。次に、b * cの結果をaに追加するには、式を再度スキャンする必要があります。
式がますます複雑になるにつれて、式を何度もスキャンするこの種のアプローチは非効率的になります。
この非効率性を克服するために、式を接尾辞または接頭辞に変換して、スタックデータ構造を使用して簡単に評価できるようにします。
#2)式の解析/評価
スタックを使用して、実際の式の評価も実行できます。この場合、式は左から右にスキャンされ、オペランドがスタックにプッシュされます。
演算子が検出されるたびに、オペランドがポップアウトされ、操作が実行されます。操作の結果は再びスタックにプッシュされます。式がスタックを使用して評価され、式の最終結果が通常はスタックの現在の最上位になるこの方法。
#3)ツリートラバーサル
ツリーデータ構造をトラバースして、さまざまな方法で各ノードにアクセスできます。また、ルートノードにいつアクセスしたかによって異なります。
- inOrderトラバーサル
- トラバーサルの事前注文
- postOrderトラバーサル
ツリーを効率的にトラバースするために、スタックデータ構造を利用して、スタック上の中間ノードをプッシュし、トラバースの順序を維持します。
#4)ソートアルゴリズム
クイックソートのようなソートアルゴリズムは、スタックデータ構造を使用してより効率的にすることができます。
#5)ハノイの塔
これは、n個のディスクと3つのタワーが関係する古典的な問題であり、問題は、3番目のタワーを中間として使用してディスクを1つのタワーから別のタワーに移動することです。
スタックは基本的にディスクを移動するために使用されるタワーとして機能するため、スタックを使用してこの問題に効率的に取り組むことができます。これは、スタックに移動するディスクをプッシュするためです。
結論
スタックは最も単純なデータ構造であり、プログラムとして実装するのが簡単です。 LIFO(後入れ先出し)アプローチを使用しました。つまり、最後に入力された要素が最初に削除された要素です。これは、スタックが要素の追加(プッシュ)と削除(ポップ)に一方の端のみを使用するためです。
スタックデータ構造は、ソフトウェアプログラミングで多くの用途があります。その中で目立つのは表現評価です。式の評価には、式を中置から後置または接頭辞に変換することも含まれます。また、式を評価して最終結果を生成することも含まれます。
このチュートリアルでは、スタックの図と実装、およびそのさまざまな操作について説明しました。
次のチュートリアルでは、キューのデータ構造について詳しく学習します。
=> 専門家による完全なC ++コースについては、こちらをご覧ください。
推奨読書