-1

我是数据结构和 C 的新手。这段代码在创建和插入节点时可以正常工作,但是当我调用 destroy 函数时,它的 case a Segmentation Fault。如果我将所有代码放在主函数而不是其他函数中,它似乎可以正常工作。

这个错误是什么情况:

destroy

delete IF仅删除链表的头部

谁能向我解释这有什么问题?

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

typedef struct node
{
    int value;
    struct node *next;
} node;

node *create_node(int value);
unsigned char insert(node *head, int value);
unsigned char delete_node(node *head, node *old_node);
node *search(node *head, int value);
unsigned char destroy(node *head);

int main(void)
{
    node *head = create_node(1);
    insert(head, 3);
    insert(head, 2);

    destroy(head);

    for(node *i = head; i != NULL; i = i -> next)
    {
        printf("%i\n", i -> value);
    }
}

// Will create a node and return it if succeeded else it will return NULL
node *create_node(int value)
{
    node *new_node = malloc(sizeof(node));

    // Check if the node created successfully or not
    if (new_node == NULL)
    {
        return NULL;
    }

    new_node -> value = value;
    new_node -> next = NULL;

    return new_node;
}

// Insert the node to a list at the beginning of it, return 0 if succeed else number NOT 0
unsigned char insert(node *head, int value)
{
    node *new_node = create_node(value);

    // Check if the node created successfully or not
    if (new_node == NULL)
    {
        return 1;
    }

    // Check if the List is exist or not
    if (head == NULL)
    {
        return 2;
    }

    new_node -> next = head -> next;
    head -> next = new_node;

    return 0;
}

// Delete the node, return 0 if succeeded else number NOT 0
unsigned char delete_node(node *head, node *old_node)
{
    // Check if the node is exist or not
    if (old_node == NULL)
    {
        return 1;
    }

    node *back = head;

    // If delete the first node ONLY
    if (head == old_node)
    {
        free(old_node);
        old_node = NULL;
        return 0;
    }

    while (back -> next != old_node)
    {
        back = back -> next;
    }

    back -> next = old_node -> next;
    free(old_node);

    return 0;
}

// destroy the whole linked list, returns 0 if destroid successfully else number NOT 0
unsigned char destroy(node *head)
{
    // Check if the List is exist or not
    if (head == NULL)
    {
        return 1;
    }

    node *temp = head;

    while (temp != NULL)
    {
        temp = temp -> next;
        destroy(temp);
        delete_node(head, temp);

    }

    delete_node(head, head);

    return 0;
}

// return Pointer to node if founded it else return NULL
node *search(node *head, int value)
{
    while (head != NULL)
    {
        // If founded it return it's pointer
        if (head -> value == value)
        {
            return head;
        }
        else
        {
            head = head -> next;
        }
    }
    return NULL;
}
4

2 回答 2

0

我不知道问题出在哪里,但我确实观察到您的distroy (sic...)函数不必要地复杂。如果您的目的是销毁整个列表,则无需调用destroy_node例程。只需执行以下操作:(伪代码 ...)

while (head != NULL) {
   temp = head->next;
   free(head);
   head = temp;
}

你的destroy_node例行程序看起来也不必要地复杂。只有两种情况需要考虑:删除head节点,以及删除不是头节点的节点。 (伪代码)

if (node == NULL) return;
if (node == head_node) {
   head_node = head_node->next;
   free(node);
} else {
   temp = head_node;
   while ((temp != NULL) {
     if (temp->next == node) {
        temp->next = temp->next->next;  // link it out of the list
        free(node);
        return;
     } else {
        temp = temp->next;
     }
  }
}
于 2020-02-13T22:00:04.147 回答
0

你的问题在这里:

while (temp != NULL)
{
   temp = temp -> next;
   delete_node(head, temp);
}  

你的函数delete_node(node *head, node *old_node)最后执行:

free(old_node); // you free temp !

如果你释放了这个内存,你没有设置old_nodeNULL你不能在这里循环第二次(因为 temp 已删除):

while (temp != NULL)
{
   temp = temp -> next;
   delete_node(head, temp);
} 
于 2020-02-13T22:08:34.043 回答