2

リンクリストと、構造体とポインターを使用してCでリストを作成する方法について学習しています。以下に例を示します。私の理解では、呼び出さpush()れたものは、引数としてヘッドノードが存在する構造体の開始メモリ位置を渡します。push()関数のパラメーターは、structノードをポインターへのポインターとして受け取るため、実際のコピーではなく、参照として渡されます。したがって、最初のポインタはstruct node** headrefヘッドノードのメモリ位置へのポインタであり、2番目のポインタは値を指します。これはヘッドノードが指す次のメモリ位置です。構造体ノード内にメモリを割り当てることにより、newnodeという新しいノードを作成します。次に、このノード内にint型のデータを作成します。

さて、私が言ったことがすべて正しいと仮定すると、次の部分は私が混乱していることです。

newNode->next= *headRef; 

私が理解できることからのこの行は逆参照しているheadrefので、これはheadrefヘッドノードを指しているだけです。headref次に、が指しているものが次に指すポインターにもなるポインター操作があります。これに基づいて、新しいnode(newnode)の次のポインターはヘッドポインターを指します。

私も混乱している次の行は次のとおりです。

*headRef = newNode;

逆参照されたheadrefポインターが指しているのはヘッドノードであり、これで新しいノードを指します。

これに基づいて、intデータと新しいノードをヘッドにリンクする次のポインターを持つnewnodeと呼ばれる新しいノードがあるはずです。次に、headrefポインター(またはヘッドノードですか?)が新しいノードを指します。newnodeの次のポインターが2番目のノードを指している必要があるため、これが正しくないことはわかっています。これにより、newnodeを構造体でリンクできるようになります。また、上記の2行のコードで、ポインターへのポインターと逆参照を理解しているとは思いません。

コード:

void Push(struct node** headRef, int data) {
  struct node* newNode = malloc(sizeof(struct node));

  newNode->data = data;
  newNode->next = *headRef;
  *headRef = newNode;
}

void PushTest(void) {
  struct node* head = BuildTwoThree(); // suppose this returns the list {2, 3}

  Push(&head, 1);
  Push(&head, 13);
  // head is now the list {13, 1, 2, 3} 
}
4

4 に答える 4

0

Ok。説明できると思います。

headリンクリストのヘッドポインタです。headRef頭を指す。*headRefヘッドポインタもそうです(参照渡し)。

したがってnewNode->next、構造体の先頭を指すようになります(値は2であるため、ノードが前面に挿入されます)。

この行*headRef = newNode; *headRefに値が割り当てられているnewNodeため、元の構造ではにhead変更されます。newNode

ここでも、を渡す&headと、head値1を含むが渡されます。

于 2013-03-01T09:28:19.320 に答える
0
void Push(struct node** headRef, int data) {

headRefには、構造体ノードが配置されているアドレスのアドレスが含まれています。PushTest関数のヘッド変数のアドレスです。

struct node* newNode = malloc(sizeof(struct node));

ここで、newNodeを作成しました。これには、ノード構造体が配置されているメモリのアドレスが含まれています。

newNode->data = data;

newNodeのデータをPush関数に渡されたデータパラメータの値に設定します-OK 。

newNode->next = *headRef;

newNode-> head変数 にある構造のアドレスの横に設定します。たとえば、私たちが書いた場合

 void Push(struct node* head, int data) {
 ...
 newNode->next = head;

次に、head変数をnewNodeに変更する必要があります。ヘッド変数が参照によって渡された場合、C ++のように、これを簡単に記述できます。

void Push(struct node* &head, int data) {
...
head = newNode;

ただし、プレーンCでは、head変数が配置されているアドレスを渡す必要があるため、 Push関数で作成した構造体newNodeへのポインターをそのアドレスに書き込むことができます。

*headRef = newNode;

これは、アドレスがheadRef変数内にある変数にnewNodeポインターを書き込むことと同じです。

そして、あなたの論理に問題があります:

push()関数のパラメーターは、structノードをポインターへのポインターとして受け取るため、実際のコピーではなく、参照として渡されます。

実際には、参照ではなく、ノード変数のアドレスを含む一時変数のコピーを渡します。C ++には参照渡しメソッドがあり、アンパサンドを使用して、関数に渡される変数が元の変数のコピーではなく参照であることを宣言します。

于 2013-03-01T09:36:28.103 に答える
0

あなたは実際には正しく、同時に正しくありません。このpush関数は、リストの先頭に新しいノードを追加します。この関数が呼び出された後、新しいノードは newheadになり、前のheadノードはリストの 2 番目 (次の) ノードになります。したがって、あなたの観察は正しいですが、結論はそうではありません。

すべてのポインターとその内容を監視しながら、デバッガーでコードをステップ実行して、何が起こるかを確認することをお勧めします。それはあなたにとって物事をより明確にするかもしれません。

于 2013-03-01T09:17:40.283 に答える
0

簡単に参照できるように、これをここにコピーしましょう。

1   void Push(struct node** headRef, int data) {
2     struct node* newNode = malloc(sizeof(struct node));
3     newNode->data = data;
4     newNode->next = *headRef;
5     *headRef = newNode;
6   }

簡単にするために、行に番号を付けました。

現在、それ自体は、リストのヘッダーを保持していた変数headRefへのポインターにすぎません。したがって、それ自体には有用な情報は含まれていません。そのポインターを逆参照することで、変数自体の内容( in )にアクセスできるようになります。したがって、基本的には にアクセスする方法です 。が最上位ノードであるため、同じアドレスであるため、同じ値を保持します。4 行目で行うことは、 の値(つまり の値) を新しいノードの次のリンクに割り当てることです。同様に、5 行目は新しいノードを に割り当てます。これは、 へのポインタであるため、 に割り当てるのと同じです。つまり、headPushTest()*headRefheadhead*headRef*headRefhead*headRefheadheadRefhead*headRefの値ですhead

ここで重要な点は、headRefは への参照 (ポインター)headであるため*headRef、 とheadは同等です (スコープ ルールは別として)。

于 2013-03-01T09:32:47.643 に答える