【问题标题】:Pointers in Structure pointing to another strucutre结构中的指针指向另一个结构
【发布时间】:2019-08-21 15:11:49
【问题描述】:

我试图了解链表中的指针是如何工作的。到目前为止,我在试图弄清楚指针指向的位置以及类型结构的指针如何工作时遇到了很多麻烦(我知道我们需要从堆中分配内存但不太明白,但也许这是一个完全不同的问题)。

让我们采用这个结构:

typedef struct Node {
    int data;
    struct Node *link;
} Node;

我认为现在会发生的是:

  1. 假设您在主函数中有一个 Node 类型的指针 Node* p,这是分配的内存(使用 malloc)。

  2. 现在,如果我们有一些数据 p->data=5;,p 指向该数据的开头(至少这是我认为正在发生的事情)。

link 到底指向哪里?

所以现在,我遇到了这段特殊的代码:

typedef struct Node {
    int data;
    struct Node *link;
} Node;

typedef struct List {
    Node* head;
    int number_of_nodes;
} List;

所以我的大脑完全混乱了! .

现在在List 结构中,head 在做什么?它指向什么?您将如何使用这两个列表创建一个链表??

我真的在尽我最大的努力去理解链表是如何工作的,但是所有的指针都让它很难跟踪。你可能会建议我从一些简单的事情开始,我做到了,我已经提到了我的理解程度。但是第二个结构中的head 指针完全让我偏离了轨道!

如果有人可以在跟踪指针的同时帮助我解释它,那会让我的生活变得更加轻松。

【问题讨论】:

  • en.wikipedia.org/wiki/Linked_list上方的图片。此时head 将指向第一个单元格。请注意,指针不是指向数据,而是指向整个两块单元格。当然,列表中的每个元素都是它自己的 Node 实例。
  • 请不要描述您的代码,而是显示一个小示例。你可以edit你的问题。
  • 我试图解释我的理解程度,以便我们可以从某个地方开始
  • 谷歌“链表教程”,你应该会发现一些有用的东西

标签: c pointers linked-list singly-linked-list


【解决方案1】:

链接到底指向哪里?

link 指向另一个相同类型的对象:

+------+------+     +------+------+     +------+------+
| data | link |---->| data | link |---->| data | link | ----> ...
+------+------+     +------+------+     +------+------+

现在在结构List中,head在做什么?它指向什么?

head 指向列表中的第一个节点:

+-----------------+     +------+------+     +------+------+ 
| head            |---->| data | link |---->| data | link |----> ...
+-----------------+     +------+------+     +------+------+
| number_of_nodes |
+-----------------+

我真的在尽我最大的努力去理解链表是如何工作的,

别难过——链表让我在我的数据结构类(我的第一个“硬”CS 类)中陷入了循环。我比我的同学花了整整一周的时间来理解这个概念。希望图片有所帮助。

编辑

如果你有一个指向结构列表、分配的内存等等的指针会发生什么?那么它指向哪里(根据图表,顺便说一句确实有帮助)

所以,假设您有以下代码:

/**
 * Create a new list object.  head is initially NULL,
 * number_of_nodes initially 0.
 */
List *newList( void )
{
  List *l = malloc( sizeof *l );
  if ( l )
  {
    l->head = NULL;
    l->number_of_nodes = 0;
  }
  return l;
}

int main( void )
{
  List *l = newList();
  ...
}

那么你的图片是这样的:

+---------+       +--------------------+
| l: addr | ----> | head: NULL         |
+---------+       +--------------------+
                  | number_of_nodes: 0 |
                  +--------------------+

(addr代表任意内存地址)

现在假设您将一个节点添加到列表中:

/**
 * Create a new node object, using the input data
 * link is initially NULL
 */
Node *newNode( int data )
{
  Node *n = malloc( sizeof *n );
  if ( n )
  {
    n->data = data;
    n->link = NULL;
  }
  return n;
}

void insertNode( List *l, int data )
{
  Node *n = newNode( data );
  if ( n )
  {
    /**
     * If list is initially empty, make this new node the head
     * of the list.  Otherwise, add the new node to the end of the
     * list.
     */
    if ( !l->head ) // or n->head == NULL
    {
      l->head = n;
    }
    else
    {
      /**
       * cur initially points to the first element in the list.  
       * While the current element has a non-NULL link, follow
       * that link.
       */
      for ( Node *cur = l->head; cur->link != NULL; cur = cur->link )
        ; // empty loop body
      cur->link = n;
    }
    l->number_of_nodes++;
  }
}

int main( void )
{
  List *l = newList();
  insertNode( l, 5 );
  ...
}

现在你的图片是这样的:

+---------+       +--------------------+      +------------+
| l: addr | ----> | head: addr         | ---> | data: 5    |
+---------+       +--------------------+      +------------+
                  | number_of_nodes: 1 |      | link: NULL |
                  +--------------------+      +------------+

您可以添加另一个节点:

int main( void )
{
  List *l = newList();
  insertNode( l, 5 );
  insertNode( l, 3 );
  ...
}

那么你的图片就变成了

+---------+       +--------------------+      +------------+        +------------+
| l: addr | ----> | head: addr         | ---> | data: 5    |   +--> | data: 3    |
+---------+       +--------------------+      +------------+   |    +------------+
                  | number_of_nodes: 2 |      | link: addr | --+    | link: NULL |
                  +--------------------+      +------------+        +------------+

当然,您会想要添加一些错误检查和消息,以防无法分配节点(发生这种情况)。您可能需要一个有序列表,其中元素按顺序插入(升序、降序等)。但这应该让您了解如何构建列表。

您还需要删除项目并释放内存的函数。以下是我如何释放整个列表:

void freeList( List *l )
{
  Node *prev, *cur = l->head;
  while( cur && cur->link )
  {
    prev = cur;
    cur = cur->link;
    free( prev );
  }
  free( cur );
}

int main( void )
{
  List *l = newList();
  ...
  freeList( l );
  free( l );
  ...
}

【讨论】:

  • 如果你有一个指向结构列表、分配的内存和所有的指针会发生什么?它指向哪里(根据图表,顺便说一下)
  • @bobthebuilder List 是一种类型。你不能有一个类型的指针(但你可以有一个“类型指针”类型),但你可以有一个类型的对象的指针。
  • 当然,links 和 head 在您分配或初始化它们之前不会指向任何有效的位置。
【解决方案2】:

…结构类型的指针…

指针不能属于类型结构。指针可以指向一个结构。

C 有对象。对象包括charintdouble、结构和其他东西。结构是组合在一起的对象的集合。

在main中,如果你用Node *p;定义p,那么你就有一个指针p。它没有价值,因为你没有给它一个价值。当您执行p = malloc(sizeof *p); 时,您请求足够的内存来容纳p 指向的事物的大小(*p)。如果malloc 返回一个非空指针,那么p 指向一个Node 结构。

那么p->data 指的是该结构的data 成员。 p->data(*p).data 的简写,其中*p 表示“p 指向的对象”,.data 表示“该对象中的data 成员”。

p = malloc(sizeof *p);p->data = 5; 之后,p->link 不指向任何内容,因为您尚未为其分配值。在链表中,您将使用malloc 为另一个Node 获取内存,然后将p->link 设置在一个Node 中以指向新的Node。在每个Node 中,其link 成员指向列表中的下一个Node。除了在最后一个Node 中,p->link 被设置为一个空指针,表示它是最后一个Node

List 中,您可以将head 设置为指向Node 对象列表中的第一个Node

【讨论】:

    猜你喜欢
    • 2017-07-13
    • 2018-04-25
    • 1970-01-01
    • 2018-09-11
    • 2013-08-26
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    • 2019-03-18
    相关资源
    最近更新 更多