【问题标题】:Array of Linked Lists in C: initializing and inserting?C中的链表数组:初始化和插入?
【发布时间】:2018-03-01 10:11:30
【问题描述】:

我需要创建一个链表数组(如图),这就是我目前所做的:

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

int main(void) {
    Node* link[5];
    for(int q = 0; q < 5; q++) {
        link[q] = malloc(sizeof(struct Node));
        link[q] = NULL;
    }
}

自从我在 C 语言中使用链表已经有一段时间了,所以我忘记了很多语法,而且我很难想象在编写链表时到底发生了什么。如果我没记错的话,当我在代码中调用 malloc 时,我正在创建一个没有任何内容的节点?

我想将它初始化为指向 NULL。我这样做了

link[q] = NULL;

我说这就是记忆中的样子对吗?

|1| -> 空

|2| -> 空

|3| -> 空


我的下一个问题是将数据插入到链表中。

(参考图片):如果我想在数组的第三个索引中插入另一个元素([3]-> d -> NULL)

这是正确的吗?

Node* newNode = link[3];
newNode->data = 1;
link[3] = newNode;

感谢您的帮助!

【问题讨论】:

  • 插入无效。再次出现内存泄漏。看我的回答。
  • 谢谢!将尽快编辑:)
  • 请问为什么会出现内存泄漏?
  • 调用 malloc 而不是 newNode = link[3];正如它所写的那样,你必须写 newNode->next = link[3];

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


【解决方案1】:

这个循环

Node* link[5];
for(int q = 0; q < 5; q++) {
    link[q] = malloc(sizeof(struct Node));
    link[q] = NULL;
}

导致内存泄漏,因为首先分配了内存,然后指针被 NULL 覆盖。这样分配的内存地址就丢失了。

你可以写

Node* link[5] = { 0 };

这是一个演示程序,展示了如何将节点添加到列表数组的元素中。 int 类型的数据成员 data 的 Insetad 我正在使用 char 类型的数据成员 data 来获取可见性。

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

typedef struct Node 
{
    char data;
    struct Node *next;
} Node;


int push_front( Node **head, char data )
{
    Node *new_node = malloc( sizeof( Node ) );
    int success = new_node != NULL;

    if ( success )
    {
        new_node->data = data;
        new_node->next = *head;
        *head = new_node;
    }

    return success;
}

void output( Node **head )
{
    for( Node *current =*head; current != NULL; current = current->next )
    {
        printf( "%c ", current->data );
    }
    printf( "%s", "NULL" );
}

void display( Node **set, size_t n )
{
    for ( size_t i = 0; i < n; i++ )
    {
        output( set++ );
        putchar( '\n' );
    }
}

#define N   5

int main(void) 
{
    Node * link[N] = { 0 };

    push_front( &link[0], 'b' );
    push_front( &link[0], 'a' );
    push_front( &link[1], 'c' );
    push_front( &link[2], 'd' );

    display( link, sizeof( link ) / sizeof( *link ) );

    return 0;
}

程序输出是

a b NULL
c NULL
d NULL
NULL
NULL

【讨论】:

  • 在你的函数push_front中,你为什么要这样做? [int成功=新节点!=空; ] 是否会有 new_node 指向 NULL 的情况(在为它分配空间之后?尤其是函数的目的是为它收集数据?)。为什么我们返回成功的价值?是否需要返回值?将函数声明为“void”不一样吗?
  • @Katrina 函数 malloc 可能会失败。您需要一种方法来确定节点是否已成功添加到列表中。
  • 再次感谢您! :)
  • 在他的例子中,他知道link的大小是5。如果你不知道数组的大小,你会怎么做?
  • 我们怎样才能给每个节点一个结构体?
【解决方案2】:

据我了解你的程序,下面的语句是不必要的:

link[q] = malloc(sizeof(struct Node));

由于需要从 NULL 指针开始,所以 link[q] = NULL;刚刚好。

要在列表中插入项目,您应该为每个项目分配内存,所以它应该变成这样:

Node* newNode = malloc(sizeof(struct Node));
newNode->data = 1;
newNode->next = link[3];
link[3] = newNode;

它应该可以工作,虽然我没有测试它。

【讨论】:

  • 谢谢!我提取了您的插入代码,我认为在为 newNode 分配空间之后,您必须使用 newNode = link[3] 将其指向链接 [3] 所指向的内容
  • 好吧,如果将分配内存的指针保存在 newNode 中,那么您也需要将指针分配给 link[3],但反之则不然。所以应该是 link[3] = newNode.
  • 我的错误。我实际上指的是 newNode->next = link[3],起初我认为是 newNode = link[3]。还是谢谢你:)
【解决方案3】:

您已经有一个由 5 个指向节点的指针组成的数组,即link。您只需执行以下操作即可将它们设置为不指向任何内容:

for (size_t i = 0; i < sizeof link / sizeof *link; ++i)
 link[i] = NULL;

在这里你不应该分配任何新的存储,因为你不需要实际的节点,你只需要指向节点的指针并且你已经有了它们。

您的代码首先分配,然后立即用NULL 覆盖malloc() 返回的指针,实际上永远失去了该内存。不好。

当你想真正创建一个节点时,你需要分配它并将它链接到正确的列表中。

【讨论】:

  • 好点!感谢您的洞察力。这意味着我要插入的代码应该更像... Node *newNode = malloc(sizeof(struct Node)) ?
【解决方案4】:

首先,如果您不确定是否看到某些内容,最好的检查方法是打印出来。

其次,你的代码有错误——

    link[q] = malloc(sizeof(struct Node));
    link[q] = NULL;

在这里,您创建了一个大小为 struct Node 的新指针 void*,然后当您将 NULL 保存在变量 Link[i] 中时,您会失去他,您有 2 个选项:

  1. 分配链接,然后用defualt fields初始化它,例如-data =-1
  2. 在初始化之前不要分配NULL并将其放入everty节点中

我的建议,选择 2,并且仅当您需要添加新节点分配时。

【讨论】:

    猜你喜欢
    • 2016-09-20
    • 2023-03-13
    • 2021-05-25
    • 2020-07-04
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2023-03-19
    • 2021-06-08
    相关资源
    最近更新 更多