使用malloc()生成链接列表

时间:2018-10-13 20:40:26

标签: c malloc

如何在链接列表生成中使用malloc?我看不到它如何用于生成链表,而不是为链表保留内存

提示:按Ctrl + F并查找“ (***)”(不带引号)以找到确切的代码位置

示例1:

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

struct LinkedList {
    int data;                   /* The data part of the linked list */
    struct LinkedList *next;    /* The pointer part of the linked list */
};  

int main(void) {

    /* Generate the 1st node ("head")  */
    struct LinkedList *head     /* I am not sure what this pointer */  
    head = NULL;                /* is doing to the struct*/
    head = malloc(sizeof(struct LinkedList));   /* Head points to null. Now
                                                 * malloc() is being called  
                                                 * and is assigned to head. 
                                                 * Next line implies head is 
                                                 * already pointing to a 
                                                 * linked list, which means 
                                                 * malloc() is making a new 
                                                 * strucuture (***) */

    /* Generate the second node */
    head -> data = 1; // This implies head is already pointing to a linked list
    head -> next = malloc(sizeof(struct LinkedList));

    /* Generate the third node */
    head -> next -> data = 2;
    head -> next -> next = malloc(sizeof(struct LinkedList));

    /* Generate the fourth node */

    head -> next -> next -> data = 3;
    head -> next -> next -> next = NULL;

    return 0;
}

示例2:

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

struct LinkedList {
    int data;
    struct LinkedList *next;
}; // notice the semi-colon!


int main(void) {

    struct LinkedList *head = NULL;     /* why is it doing this? */
    struct LinkedList *second = NULL;
    struct LinkedList *third = NULL;

    // Generate the node structure:
    /* how does (struct LinkedList*) affect malloc? (***) */
    head = (struct LinkedList*)malloc(sizeof(struct LinkedList));
    second = (struct LinkedList*)malloc(sizeof(struct LinkedList));
    third = (struct LinkedList*)malloc(sizeof(struct LinkedList));

    // Now fill the first node with info:
    head->data = 1;         /* assign data to the first node */
    head->next = second;    /* Link the first node ("head") with the second 
                             * node ("second") */

    // Now fill the second node with info:
    second->data = 2;       /* assign data to the second node */
    second->next = third;   /* Link the second node to the third node */

    // Now fill the second node with info:
    third->data = 3;        /* assign data to the second node */
    third->next = NULL;     /* Since node 3 is our last node to the link list, 
                             * we give it the value of NULL */

    return 0;
}

教科书将链接列表描述为链结构。 Malloc()用于动态内存管理。但是,在这些示例中,使用malloc声明了新结构,我不明白为什么。我以为它只能保留内存

例如,在示例1中,malloc()保留了该结构的空间,但没有“创建”它(struct LinkedList var将创建一个新的链表并将其存储在var中)< / p>

例如,在示例2中,看起来malloc()受到(struct LinkedList*)(即(struct LinkedList*)malloc(sizeof(struct LinkedList));)的影响,但是我不确定

3 个答案:

答案 0 :(得分:2)

您可以像在相互连接的盒子上一样查看链接列表:

 ______        ______        ______
| data |      | data |      | data |
|______|      |______|      |______|
| next |      | next |      | next |
|______|----->|______|----->|______|----->NULL

每个方框都在您的位置:

struct LinkedList
{
    int data; /* The data part of the linked list */
    struct LinkedList *next; /* The pointer part of the linked list */

};

您的“盒子”的大小(取决于拱门)让我们以x64 Linux机器等于 到16个字节。要创建链接列表数据类型,您需要将此框存储在内存中(堆栈/堆)并连接它们。

我注意到一个“盒子”的大小是16字节,应该存储在内存中。对于用户空间中的内存管理,您可以使用malloc(),这里重要的事情是malloc() 没有“声明”任何内容 ,它 只为堆上的一个“盒子”分配一部分内存 ,而您使用sizeof()运算符为“盒子”要求恰好16个字节。

struct LinkedList *head = malloc(sizeof(struct LinkedList));

它为您的“盒子”分配内存,现在看起来像这样:

 ______ 
| data |
|______|
| next |
|______|----->NULL

执行此操作时:

head->next = malloc(sizeof(struct LinkedList));

您为另一个“盒子”分配内存并连接它们:

 ______        ______  
| data |      | data |      
|______|      |______|      
| next |      | next |      
|______|----->|______|

执行此操作时:

struct LinkedList *head = malloc(sizeof(struct LinkedList));     
struct LinkedList *second = malloc(sizeof(struct LinkedList));
struct LinkedList *third = malloc(sizeof(struct LinkedList));

您在内存中的每个位置创建16个字节的三个“框”。而且他们暂时不连接,它们只位于内存中;

   head         second      third
  ______        ______      _____
 | data |      | data |    | data |
 |______|      |______|    |______|   
 | next |      | next |    | next |
 |______|      |______|    |______|

您将他们连接起来就是这样:

head->next = second;
second->next = third;
third->next = NULL;

 head          second        third
 ______        ______        ______
| data |      | data |      | data |
|______|      |______|      |______|
| next |      | next |      | next |
|______|----->|______|----->|______|----->NULL

通常在函数中使用第二种方法,例如用于ex add_node_front()

void add_node_front(struct LinkedList **head_ref, int data) 
{ 
    /* 1. allocate node */
    struct LinkedList *new_node = malloc(sizeof(struct LinkedList)); 

    /* 2. put in the data  */
    new_node->a  = data; 

    /* 3. Make next of new node as head */
    new_node->next = (*head_ref); 

    /* 4. move the head to point to the new node */
    (*head_ref)    = new_node; 
} 

答案 1 :(得分:1)

在第二个示例中,您还可以静态分配内存:

struct LinkedList head;
struct LinkedList second;
struct LinkedList third;

然后您需要使用点运算符进行访问:

head.data = 1; //assign data to the first node
head.next = &second;

您还可以使用数组

struct LinkedList nodes[3];
node[0].data = 1;
node[0].next = &node[1];

以此类推。

因此,malloc命令对于链接列表的概念不是必需的。 但是对于您之前不知道的许多应用程序,您的链表将有多大。并且元素和顺序将在运行时更改。因此,在这种情况下,使用malloc / free进行动态内存分配确实很有帮助。

答案 2 :(得分:0)

  

如何在链接列表生成中使用malloc?

malloc用于动态分配内存。创建链接列表时,可以使用malloc为列表的节点分配内存。 了解有关malloc here的更多信息。

来自示例1:

head = malloc(sizeof(struct LinkedList));

来自示例2:

head = (struct LinkedList*)malloc(sizeof(struct LinkedList));

唯一的区别是,在示例2中,您显式强制转换malloc结果。 malloc的返回类型为void *,并且void *可以强制转换为所需的类型,但是无需这样做,因为它将被自动转换。因此,投射不是必需的。实际上,不强制转换malloc。选中this

除了内存分配顺序外,两个示例在功能上都是相同的。 在示例1中,您将分配内存给head指针,然后分配给head -> next指针,然后分配给head -> next -> next指针。

在示例2中,您将内存分配给headsecondthird指针,然后将second分配给head -> nextthirdhead -> next -> next


其他:

始终检查malloc的返回值,例如:

head = malloc(sizeof(struct LinkedList));
if (NULL == head) {
    fprintf (stderr, "Failed to allocate memory");
    exit(EXIT_FAILURE);
}

此外,一旦完成,请确保free动态分配的内存。遵循良好的编程习惯。