こんにちは、私は工科大学の2年生です。 健康上の理由でいくつかのプログラミングペアをスキップした後、StackやQueueなどのトピックの誤解に出会いました。 数日後、試行錯誤を繰り返して、それが何で、何で食べられたのかがようやくわかりました。 理解にそれほど時間がかからないように、この記事では「スタック」とは何か、どのように、どのような例を理解したかについて説明します。 気に入ったら、2番目のパートを書きます。このパートでは、すでに「キュー」などを取り上げます。
理論
スタック
かなり完全な定義ですが、おそらく初心者にとっては理解するのが少し難しいでしょう。
したがって、私が最初に注目したいのは、スタックを生の物の形で提示することです。 私が最初に思いついたのは、一番上の本が一番上にある本のスタックの形での解釈でした。
実際、スタックは、シート、ノート、シャツなどのスタックであるかどうかにかかわらず、あらゆるアイテムのスタックとして表すことができますが、本を使用した例が最も最適だと思います。
したがって、スタックは何で構成されていますか。
スタックはセル(この例ではブック)で構成されます。セルは、データを含む構造体の形式で提示され、次の要素へのこの構造体の型へのポインターです。
難しいですか? 関係ありません理解しましょう
この写真はスタックを模式的に示しています。 「Data / * next」という形式のブロックがセルです。 * nextは、次のように、次の要素を指します。つまり、* nextポインターは次のセルのアドレスを格納します。 * TOPポインターはスタックの先頭を指します。つまり、そのアドレスを格納します。
理論が終了したら、実践に移りましょう。
練習する
まず、「セル」となる構造を作成する必要があります
struct comp { // comp( component) int Data; //- ( , int key; char Data; - - ) comp *next;// comp };
初心者の場合、ポインターがcomp型である理由、または構造型compへのポインターである理由が明確でない場合があります。 * nextポインターがcomp構造を格納するためには、この構造のタイプを示す必要があることを説明します。 言い換えれば、ポインターが保存するものを指定します。
「セル」を設定したら、関数の作成に進みます。
機能
「スタック」を作成する/「スタック」にアイテムを追加する機能
要素を追加するとき、2つの状況があります。
- スタックは空なので、作成する必要があります
- スタックはすでにそこにあり、新しい要素を追加するだけです
関数s_pushを呼び出して、コードに移りましょう。
void s_push(comp **top, int D) { // void( ) comp *q; // q comp. q = new comp(); // q->Data = D; // Data if (top == NULL) { // , *top = q; // } else // { q->next = *top; // , . . *top = q; //, } }
もう少し詳しく分析しましょう。
まず、関数が** top、つまり、ポインターへのポインターを受け入れる理由。最も明確になるように、この問題の説明は後で行います。 次に、 q-> next = * topとその意味->の意味について詳しく説明します。
->は、大まかに言えば、私たちの構造に入り、そこからこの構造の要素を取り出すことを意味します。 行q-> next = * topでは、セルからnext * next要素へのポインターを取得し、それを* topスタックのtopを指すポインターに置き換えます。 つまり、新しいアイテムからスタックの最上部に接続します。 本のように複雑なことは何もありません。 新しい本を山の上に正確に配置します。つまり、新しい本から本の山の上部への接続を実行します。 この後、新しい本は自動的にトップになります。スタックは本のスタックではないため、新しい要素がトップであることを示す必要があります。 。
データに従って「スタック」からアイテムを削除する機能
この関数は、データセルの数(q-> Data)が自分で指定した数と等しい場合、スタックから要素を削除します。
そのようなオプションがあるかもしれません:
- 削除する必要があるセルはスタックの一番上です
- 削除する必要があるセルは、最後または2つのセルの間にあります
void s_delete_key(comp **top, int N) {// top comp *q = *top; // comp () comp *prev = NULL;// , while (q != NULL) {// q , , if (q->Data == N) {// Data , if (q == *top) {// , , - *top = q->next;// free(q);// q->Data = NULL; // , NULL , " " "-2738568384" , . q->next = NULL; } else// { prev->next = q->next;// free(q);// q->Data = NULL;// q->next = NULL; } }// Data , prev = q; // q = q->next;// q } }
この場合のqポインターは、メモ帳のポインターと同じ役割を果たし、NULLになるまで( while(q!= NULL) )、つまりスタックが終了するまでスタック全体に沿って実行されます 。
要素の削除をよりよく理解するために、すでにおなじみの書籍のスタックとの類似性を引き出します。 上から本を削除する必要がある場合は削除し、その下の本が最上部になります。 ここでも同じことです。最初にのみ、次の要素がトップになることを決定する必要があります* top = q-> next; そして、そのあとでfree(q)要素を削除します;
削除する本が2冊の本の間、または本とテーブルの間にある場合、前の本は次の本またはテーブルの上にあります。 すでに理解したように、本はセルであり、テーブルはNULLであることがわかりました。つまり、次の要素はありません。 本と同じことがわかります。つまり、前のセルが次のセルに関連付けられることを意味しますprev-> next = q-> next; q-> next = NULLの場合、つまりprev-> nextがセルまたはゼロになる可能性があることに注意する価値があります 。つまり、セルがない場合(本はテーブルに置かれます)、その後、 空き(q)セルをクリアします。
また、この接続を行わないと、削除されたセルの後にあるセルのセクションにアクセスできなくなります。1つのセルを別のセルに接続する接続が失われ、このセクションがメモリ内で失われるためです。
スタックデータ出力機能
最も単純な関数:
void s_print(comp *top) { // comp *q = top; // q while (q) { // q (while(q) while(q != NULL)) printf_s("%i", q->Data);// q = q->next;// q () } }
ここでは、すべてが明確だと思います。qはスライダーとして認識される必要があるだけで、最初にインストールした上からすべてのセルを通過します。 * q = top; 最後の項目まで。
主な機能
さて、スタックを操作するための主要な関数を書き留めて、それを呼び出します。
コードを見てみましょう:
void main() { comp *top = NULL; // , , NULL // 1 5 s_push(&top, 1); s_push(&top, 2); s_push(&top, 3); s_push(&top, 4); s_push(&top, 5); // 54321 s_print(top);// s_delete_key(&top, 4); // 4, 5321 printf_s("\n");// s_print(top);// system("pause");// }
関数で、ポインターを頂点ポインターに渡した理由に戻りましょう。 実際、関数の頂点へのポインタのみを入力した場合、「スタック」は関数内でのみ作成および変更され、メイン関数では頂点はNULLのままであるか、NULLのままです。 ポインターをポインターに渡すことにより、main関数のtop * topを変更します。 関数がスタックを変更する場合、ポインターへのポインターを使用して頂点を渡す必要があるため、関数にs_push、s_delete_keyがありました。 s_print関数では、「スタック」を変更しないでください。そのため、ポインタを最上部に渡すだけです。
1、2、3、4、5の代わりに、int型の変数を使用することもできます。
おわりに
完全なプログラムコード:
#include <stdio.h>; #include <iostream>; struct comp { // comp int Data; // ( , int key; char Data; ) comp *next;// comp }; void s_push(comp **top, int D) { // void( ) comp *q; // q, . q = new comp(); // q->Data = D; // D Data if (top == NULL) { // , *top = q; // } else // { q->next = *top; // , . . *top = q; //, } } void s_delete_key(comp **top, int N) {// top comp *q = *top; // comp () comp *prev = NULL;// , while (q != NULL) {// q , , if (q->Data == N) {// Data , if (q == *top) {// , , - *top = q->next;// free(q);// q->Data = NULL; // , NULL , " " "-2738568384" , . q->next = NULL; } else// { prev->next = q->next;// free(q);// q->Data = NULL;// q->next = NULL; } }// Data , prev = q; // q = q->next;// q } } void s_print(comp *top) { // comp *q = top; // q while (q) { // q (while(q) while(q != NULL)) printf_s("%i", q->Data);// q = q->next;// q () } } void main() { comp *top = NULL; // , , NULL // 1 5 s_push(&top, 1); s_push(&top, 2); s_push(&top, 3); s_push(&top, 4); s_push(&top, 5); // 54321 s_print(top);// s_delete_key(&top, 4); // 4, 5321 printf_s("\n");// s_print(top);// system("pause");// }
実行結果
54321
5321
要素は常にスタックの一番上に追加されるため、要素は逆の順序で表示されます
結論として、私の記事に費やした時間に感謝したいと思います。この資料が、初心者プログラマーが「スタック」とは何か、それを使用する方法、そして将来問題がなくなることを理解する助けになることを本当に願っています。 コメントにあなたの意見を書いてください。また、今後私の記事を改善する方法も教えてください。 ご清聴ありがとうございました。