单链接列表:newNode函数未指向下一个节点

时间:2018-12-18 17:42:51

标签: c linked-list int nodes singly-linked-list

我目前正在C语言中尝试单链列表。 newNode函数可创建节点,而printNodes函数可打印出所有节点-看起来像这样:

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

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

void printNodes(struct Node *current_node)
{
  while(current_node != NULL)
  {
    printf("Node is: %d\n", current_node->data);
    current_node = current_node->next;
  }
}

int main()
{
  int number_1 = 2;
  int number_2 = 3;
  int number_3 = 4;

  struct Node *head;
  struct Node *second;
  struct Node *third;

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

  head->data = number_1;      
  head->next = second; 

  second->data = number_2;      
  second->next = third; 

  third->data = number_3;     
  third->next = NULL; 

  printNodes(head);

}

输出正确:

Node is: 2
Node is: 3 
Node is: 4

现在我想编写一个用于创建新节点的函数newNode,我将代码更改为:

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

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

struct Node *newNode(int number_x, struct Node *nextnode)
{
    struct Node *tmp_node;

    tmp_node = malloc(sizeof(struct Node));
    tmp_node->data = malloc(sizeof(struct Node));
    tmp_node->data = number_x;
    tmp_node->next = nextnode;

    return tmp_node;
}   

void printNodes(struct Node *current_node)
{
    while(current_node != NULL)
    {
        printf("Node is: %d\n", current_node->data);
        current_node = current_node->next;
    }
}

int main()
{
    int number_1 = 2;
    int number_2 = 3;
    int number_3 = 4;

    struct Node *head;
    struct Node *second;
    struct Node *third;

    head = newNode(number_1, second);
    second = newNode(number_2, third);
    third = newNode(number_3, NULL);

    printNodes(head);

}

编译后,我首先收到以下警告消息:

test.c:16:20: warning: incompatible pointer to integer conversion 
assigning to 'int' from 'void *' [-Wint-conversion]
tmp_node->data = malloc(sizeof(struct Node));
               ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~

输出看起来像这样:

Node is: 2

它仅显示节点head,我想next指向有问题 (例如head->next = second),但是出什么问题了?我无法解决这个问题。

谢谢

3 个答案:

答案 0 :(得分:1)

这里

tmp_node->data = malloc(sizeof(struct Node)); /* remove this statement */

datastruct Node的成员,它是一个整数,为此,您不必分配内存。您已经在这里分配了完整的结构

tmp_node = malloc(sizeof(struct Node)); /* this is enough */

也在这里

head = newNode(number_1, second);

second是什么?应该使用NULL进行初始化,例如

struct Node *second = NULL;

然后仅在newNode()函数tmp_node->next中分配正确的值

tmp_node->next = nextnode; /* now nextnode contains NULL, that's correct */

或者您可以像下面这样

head = newNode(number_1, NULL);
second = newNode(number_2, head);
third = newNode(number_3, second);

,然后在调用printNodes()时传递third而不是head。对于例如

printNodes(third);

示例代码:

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

struct Node *newNode(int number_x, struct Node *nextnode) {
    struct Node *tmp_node;
    tmp_node = malloc(sizeof(struct Node));
    tmp_node->data = number_x;
    tmp_node->next = nextnode;
    return tmp_node;
}

void printNodes(struct Node *current_node) {
    while(current_node != NULL) {
        printf("Node is: %d\n", current_node->data);
        current_node = current_node->next;
    }
}

int main(void) {
    int number_1 = 2;
    int number_2 = 3;
    int number_3 = 4;

    struct Node *head = NULL;
    struct Node *second = NULL;
    struct Node *third = NULL;

    head = newNode(number_1, NULL);
    second = newNode(number_2, head);
    third = newNode(number_3, second);
    printNodes(third);
        return 0;
}

答案 1 :(得分:1)

首先,您看到的警告(应视为错误,仅供参考)与您的整体问题无关,但仍然很重要。它既不适当,又会泄漏内存,并且具有测试意大利面的模糊外观。万一您从未做过,一种古老的厨房技术可用来检查面食是否“煮熟”,该方法是从锅中取出一小撮,然后从字面上扔到墙上,看它是否粘了。这看似多余的代码行看起来就是这样。就像你在墙上扔东西看它是否卡住了:

此:

tmp_node->data = malloc(sizeof(struct Node)); // DELETE THIS

甚至根本不会出现在您的代码中 ;下一行执行应做的事情,即:

tmp_node->data = number_x; // KEEP THIS

链接列表

虽然之前提到过的问题很严重,但这并不是您无法正确排列清单的令人羡慕的立场。这本身就是一个问题。请考虑以下内容:

struct Node *head;      // indeterminate
struct Node *second;    // indeterminate
struct Node *third;     // indeterminate

在前两个newNode调用中,您将不确定的指针值传递给最终将成为新分配的节点next指针。这很重要。颠倒了构建顺序,您可以得到想要的行为。

third = newNode(number_3, NULL);    // third is set, next points to NULL
second = newNode(number_2, third);  // second it set, next points to third
head = newNode(number_1, second);   // head is set, next points to second

显然,这样做不是理想的选择,但是只是学习事物的连接方式,这是一种实现方法。另一个方法是直接直接分配给下一个成员。例如:

head = newNode(number_1, NULL); 
head->next = newNode(number_2, NULL);
head->next->next = newNode(number_3, NULL);

这也很好,但是也不是很理想。您是否真的想建立一个包含一百个节点的链表?

向前链接链表

是一种非常简洁的方法,无需执行上述操作即可构建升序链接列表。它称为前向链接,它利用了一个指向指针的指针,该指针最初指向头部指针本身(最初为NULL):

struct Node *head = NULL;
struct Node **pp = &head; // points to a pointer, initially the head pointer

使用上述方法,我们可以将所需的许多元素链接在一起。一百 ?没问题:

for (int i=1; i<=100; ++i)
{
    // allocate a new node, storing the address at whatever pointer
    // is being addressed by the pointer-to-pointer pp. Initially it
    // will be the `head` pointer variable.

    *pp = malloc(sizeof **pp);
    (*pp)->data = i;

    // move pp to point to the next pointer of the node we just added
    pp = &(*pp)->next;
}
*pp = NULL; // terminate the list


printNodes(head);

这只是构建链接列表的一种方法。还有很多其他的方法(例如,在学校学习递归时,递归执行并不罕见)。但这可能是最简单的,几乎可以肯定是最快的。

无论如何,那比我想要的要长,但是我希望它能帮上忙。

答案 2 :(得分:0)

感谢@WhozCraig进行澄清。

正如他所提到的,second节点不知道他的输入是什么。 要分解它,如果您编写如下代码,也会发生同样的情况: int num; printf("%d",num)

由于没有初始化输入,程序不知道输入了什么。

我的程序也发生了同样的事情,没有初始化节点,所以程序不知道next-node在哪里。 但是,如果我向后编写程序,则程序现在可以理解值是什么并且可以使用它:

    //use it backwards
    third = newNode(number_3, NULL);
    second = newNode(number_2, third);
    head = newNode(number_1, second);

现在,输出正确:

Node is: 2
Node is: 3
Node is: 4

感谢您的帮助, 欢呼。