插入C中单独链接的背面

时间:2014-02-27 14:34:59

标签: c insert singly-linked-list

下面是我的节点结构声明和后面函数的插入。在main中,我声明一个头节点并将其指向NULL。然后我调用该函数,并尝试打印出第一个节点的值,但程序停止。我仍然无法弄清楚出了什么问题。

     typedef struct node {
         int val;
         struct node *next;
     } NODE;

     void insert_back(NODE *head, int val) {
     NODE *new = malloc(sizeof(NODE));
     new->val = val;
     new->next = NULL;
         if (head == NULL)
             head = new;
         else {
             NODE *p = head;
             while (p->next != NULL)
                 p = p->next;
             p->next = new;
         }
     }


     int main() {
         NODE *head = NULL;
         insert_back(head, 2);
         printf("%d", head->val);
     }

3 个答案:

答案 0 :(得分:1)

当你离开你的函数时,你在insert_back中分配的指针会丢失。为了使它能够工作,你的insert_back应该得到指针指针。

typedef struct node {
         int val;
         struct node *next;
     } NODE;

     void insert_back(NODE **head, int val) {
     NODE *new = malloc(sizeof(NODE));
     new->val = val;
     new->next = NULL;
         if (*head == NULL)
             *head = new;
         else {
             NODE *p = *head;
             while (p->next != NULL)
                 p = p->next;
             p->next = new;
         }
     }


     int main() {
         NODE *head = NULL;
         insert_back(&head, 2);
         printf("%d", head->val);
     }

答案 1 :(得分:1)

你需要传递头部的地址,而不仅仅是头部。而不是按值调用使用按引用调用

应该是insert_back(&head, 2);

在定义中更改为void insert_back(NODE **head, int val) {

答案 2 :(得分:1)

C按值传递所有。您正在向head函数传递NULL,这是一个空指针(如值insert_back)。
NULL已分配给该值的head参数变量 你正在改变那个insert_back函数的局部变量,这很好,但是也不希望改变main函数中的变量。

有两种可能的方法:

添加第二级间接(将指针传递给您想要更改的变量),或者返回 head变量,然后重新分配:

指针到指针:

void insert_back(NODE **head, int val)
{
    NODE *node = malloc(sizeof *node);
    if (node == NULL)//check if malloc was successful!
        exit(1);//or fprintf(stderr, "message"); and handle the issue
    node->val = val;
    node->next = NULL;
    if (*head == NULL)
    {
        *head = node;
        return;
    }
    NODE *tmp = *head;
    while (tmp->next != NULL)
        tmp = tmp->next;
    tmp->next = node;
}

正如您现在所做的那样调用此函数,但是传递指针的地址,而不是指针本身:

NODE *head = malloc(sizeof *head);
if (head == NULL) exit (1);
head->next = NULL;
insert_back(&head, 123);

返回head

NODE * insert_back(NODE *head, int val)
{
    NODE *node = malloc(sizeof *node);
    if (node == NULL) exit (1);
    node->val = val;
    node->next = NULL;
    if (head == NULL)
    {
        return node;//head is null, no need to assign
    }
    NODE *tmp = head;
    while (tmp->next != NULL)
        tmp = tmp->next;
    tmp->next = node;
    return head;//return node passed initially, because it will be reassigned!
}
//call like so:
head = insert_back(head, 123);

作为额外的好处,您也可以使用此功能来分配新结构:

NODE *head = insert_back(NULL, 123);//pass null pointer, will return new node and assign it to head

但同样有效:

NODE *head = insert_back(NULL, 123);
head = insert_back(head, 456);
head = insert_back(head, 789);
printf("Head: %d\nNext: %d\nTail: %d\n",
       head->val,
       head->next->val,
       head->next->next->val
);

当然,不要忘记写一个体面的功能来释放链接列表 也许,如果你还没有写过这个,这里有一个基本的例子(同样:两种方法都可以使用,但我建议使用指向指针的方法):

void free_list(NODE **list)
{
    if (*list->next == NULL)
    {//tail
        free(*list);
        *list = NULL;//assign NULL, makes a valid NULL pointer
        return;
    }
    free_list(&(*list->next));//recursive call
    //once we get here, all next-nodes are freed:
    free(*list);//free node, and again:
    *list = NULL;//make a valid null pointer
}
//call:
free_list(&head);
free(head);//will not be a problem, head is NULL pointer

可替换地:

void * free_list(NODE *list)
{//note VOID POINTER is returned (will always return NULL, though)
    if (list->next == NULL)
    {
        free(list);
        return NULL;
    }
    free_list(list->next);
    free(list);//free node, and again:
    return NULL;//make a valid null pointer
}
//call
head = free_list(head);
free(head);//not an issue here

因此,您可能会认为两者都同样安全,但如果您忘记分配第二个free_list函数的返回值会怎么样?

free_list(head);
free(head);//<--X undefined behaviour

指向的内存head已被释放,但您第二次调用free。这会让你感到悲伤:head指针无效,将无效指针传递给free会导致未定义的行为。这就是为什么第一个(指向指针)方法是更安全的选择:一旦写入,该函数将永远不会忘记为指针指定NULL。


作为助手,有几个提示:

您的main函数不返回int。使用-Wall编译此代码并通过添加return 0;语句来解决该问题 检查所有功能的返回值,包括malloc&amp; co,如果分配失败,它将返回NULL。你没有检查,所以那里存在未定义行为的风险。