11

これは私のコードではありません。私はこのウェブサイトからこのコードを取りました:

http://www.macs.hw.ac.uk/~rjp/Coursewww/Cwww/linklist.html

リンクされたリストの作成方法に関する参考資料として使用しています。何が起こっているのか少し混乱しています。誰かが私に何が起こっているのか説明してもらえますか. 混乱しているものに 1 ~ 5 のマークを付けます。

#include<stdlib.h>
#include<stdio.h>

struct list_el {
   int val;
   struct list_el * next;
};

typedef struct list_el item;

void main() {
   item * curr, * head;
   int i;

   head = NULL;   //1

   for(i=1;i<=10;i++) {
      curr = (item *)malloc(sizeof(item));
      curr->val = i;
      curr->next  = head; //2
      head = curr; //3
   }

   curr = head; // 4

   while(curr) {  //5
      printf("%d\n", curr->val);
      curr = curr->next ;
   }
  1. head = NULL → head が NULL に設定されているのはなぜですか? 私はあなたがそうしなければならないことを知っています (私は習慣からそうしています) が、その理由はよくわかりません.

  2. curr->next = head → これもよくわからなかった。「頭」の定義が間違っているかもしれませんが、通常のリンクされたリストでは、それはリストの開始ノードですか、それとも最後のノードですか? 私は常にそれが開始ノードであると想定していましたが、この行では最後のノードのように見えます。

  3. head = curr → なぜ curr に等しく設定するのですか?

  4. curr = head → そして、ループが終わった後に curr = head を設定します。

  5. while(curr) → 念のため言っておきますが、これはリストをトラバースしていて、while(curr != NULL) と同じですよね?

4

7 に答える 7

20

#1:head = NULL

ポインタを初期化しています一般に、(1)宣言時または(2)宣言直後にポインタをNULLに初期化することをお勧めします。プログラマーが誤って初期化されていないポインターを逆参照した場合、ガベージ値が返されます。多くの場合、静的アナライザーとコンパイラーが初期化されていないポインターに対して警告またはエラーメッセージを表示しない場合、これをデバッグするのは非常に困難です。

詳細については、SteveMcConnellのCodeComplete :A Practical Handbook ofSoftwareConstructionまたはWikipediaページのDefensiveProgrammingを参照してください。

#2:curr->next = head

リンクリストの作成currノードは、シーケンス内で以前に作成されたノードに「リンク」されています。

#3:head = curr

ヘッドポインタを更新しています。headポインターは、最新のedノードを指すように更新されていますmalloc

以下の図は、ステップ2と3を視覚化したものです。

最初 2番目 第3 4番目と最後

#4:curr = head

ポインタを再初期化します。この手順は、手順2に似ていますcurr->next = headcurrノードをheadに設定することにより、ループcurr内のリンクリストトラバーサルの「準備」を取得します。while同様に、ループの開始時に反復変数を0に初期化するようなものです(つまりi = 0)。このステップを視覚化するには、このステートメントが実行される前/後を示す以下の図を参照してください。

前

後

#5:while(curr)

リストをトラバースします。 それcurrが(ステップ#4からの)最初のノードを指しているとすると、このループはNULLを返すwhileまでリストをトラバースします。curr->nextより抽象的な形式では、このステートメントを。として書き直すことができwhile(curr != NULL)ます。

于 2013-03-15T21:02:34.303 に答える
5
  1. head はリストの先頭を指しています。リストは現在空であるため、null に設定されています
  2. リストにノードを追加するときは、「次の」ポインタをリストの現在の先頭に設定します。は、新しいノードをリストの先頭に置きます。
  3. 新しいノードをリストの先頭にするには、「head」を「curr」に設定します。
  4. ループが終了したら、「curr」変数を再利用してリストをトラバースします。
  5. リストの一番下から外れるまで、各ノードに「curr」を順番に設定していきます (ここで、curr->next は null です)。
于 2013-03-15T20:45:56.627 に答える
3

(1)。何かに設定する必要があり、NULL を使用することは、何も指していないと言う方法です。通常、NULL は 0 と同じです。一部の言語では、変数が自動的に nil に設定されるため、変数を初期化する必要はありません。ただし、C ではそれができないため、自分で行う必要があります。

(2)。headリストの最初のノードを指しています。最初は NULL です。これは、リストが空で、head何も指していないことを意味します。curリストに挿入する新しいノードです。curr->nextは既存のリストの最初のノードを指したいので、 にcurr->next設定されていheadます。

(3)。この時点headで、最初のノードを指していません。初めてループを通過すると、次のようになります。

curr-->node1-->NULL
         頭--^

しかし、一般的には次のようになります

curr-->node3-->node2-->node1-->NULL
          頭--^

headそのため、最初のノードを指すように更新する必要があります。currは先頭に配置された新しく作成されたノードを指しているのでhead、 と同じノードを指すように設定するだけcurrです。

(4)。プログラムの最初の部分が完了しました。 curr作成した新しいノードを追跡するために使用されたため、不要になりました。一時変数でした。この行は、リストの先頭curr = headに初期化することを意味しますcurr。別の変数を使用して読みやすくすることもできましたが、通常は一時変数の再利用が見られます。

(5)。右。はおそらく とNULL定義されて(void*)0いるので、0 と同じです。60 年代または 70 年代の非常に古いマシンを除いて、おそらく 0 以外の値を目にすることはないでしょう。論理的に while (curr != 0)は、 と同じです: と同じwhile (curr)です。

于 2013-03-15T21:18:07.460 に答える
2

最初に、 Linked List Head Is Always Null およびSimple C++ Linked Listで head が常に NULL である理由の質問に対する答えを見つけることができます。c の単一リンクリストにある初心者向けのチュートリアルです。ステートメント head=curr は、メモリを割り当てることによって、ゼロ以外の値を受け取る現在のポインターの値に NULL だったポインター head の値を関連付けました。while(curr) は、長い curr が NULL とは異なる場合に実行されるループであり、NULL は、ポインティング アドレスのゼロ値に関連付けられたマクロです。

于 2013-03-15T20:54:23.543 に答える
2

私たちは何もないところから始めています。それが

head = NULL;

と教えてくれます。まだリストがないため、アクセスできません。

1 から 10 までループしています。後ろから前にリストを作成します。HEAD は NULL であるため、「最後」(最初に作成された) は NULL を指します。

curr->next  = head; // head is NULL in the first loop

HEAD が次の新しい要素に設定されました。

head = curr;

このループの 2 回目の実行で、 head は最後に作成された項目へのポインターを格納します。新しく作成されたものはそれを指します。この新しいアイテムを最後のアイテムの前に設定します。

設定

head = curr;

次のループでヘッドに正しいポインターが含まれていることを確認するために、実行する必要があります。それまでに作成されたリストの先頭が常に格納されるため、head と呼ばれます。

//4 は実際には必要ありません。

以前の最後の操作は次のとおりです。

head = curr;

そう

curr = head;

無意味です。

そして5番目のものはリストを繰り返します。「curr」は最初の項目 (NULL 以外のアドレスを持つ) を指し、各ループで curr->next に設定されます。curr が (最後の項目で) NULL になると、ステートメントは真ではなくなります。

于 2013-03-15T20:56:16.787 に答える
2

1. head = NULL → head が NULL に設定されているのはなぜですか?
変数を初期化することをお勧めします。一部のシステムでは、宣言された変数は、アドレス空間が取得されたときにたまたまメモリ内にあったものをすべて保持します。

2. curr->next = head → これもよくわからなかった。「頭」の定義が間違っているかもしれませんが、通常のリンクされたリストでは、それはリストの開始ノードですか、それとも最後のノードですか? 私は常にそれが開始ノードであると想定していましたが、この行では最後のノードのように見えます。
はい、頭は開始ノードです。

3. head = curr → なぜ curr に等しく設定するのですか?
ここでのこのループは、新しいノードをヘッドとして追加します。スタックのように。他の方法では、テールに新しいノードを追加します。どちらの方法も「リンクされたリスト」のままです。

4. curr = head → ループ終了後に curr = head を設定します。
curr作業変数であるインデックスのように機能するため、データ構造を乱すことはありません。彼は終わった後、それをリセットしています。よろしければ「テープの巻き戻し」。

5. while(curr) → 念のため言っておきますが、これはリストをトラバースしていて、while(curr != NULL) と同じですよね?
はい、これは C で見られる暗黙的なものの 1 つです。while ループ内のすべてのものは、暗黙的while(whatnot != 0)に null == 0 です。

于 2013-03-15T20:54:09.983 に答える
0

4番目の問題では、必要ないと思いますcurr=head.ループが終わったとき、currとheadは同じノード(i=10のノード)を指していたからです。でも良い癖です。

于 2014-03-06T07:16:48.757 に答える