【问题标题】:Deleting a node appended at the end of a linked list in C删除附加在C中链表末尾的节点
【发布时间】:2018-09-03 19:55:45
【问题描述】:

我有一个链表,其中每个节点存储一个单词和一个数字。我可以在列表顶部 (push)、列表中心 (insertAfter) 和列表末尾 (append) 添加节点。我现在添加了一个删除节点的函数,它需要一个字符,它将在列表中搜索该字符并删除存储该字符的节点。

问题是deleteNode 将与添加到列表顶部的普通节点一起使用,但是当我在末尾附加一个节点或将其添加到列表中间时,它将不起作用。

Tl;dr deleteNode 适用于使用 push 创建的节点,但不适用于使用 appendinsertAfter 创建的节点。

我得到的错误是segmentation fault,所以我没有来自编译器的特定错误。我试图通过运行代码的不同部分来调试它,但我仍然找不到问题。

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


void push(struct Node** head_ref, int new_data, char *new_word)
{
    struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));

    new_node->data  = new_data;


    new_node->word= malloc(strlen(new_word));
    strcpy(new_node->word, new_word);

    new_node->next = (*head_ref);

    (*head_ref)    = new_node;
}

/* Given a node prev_node, insert a new node after the given 
   prev_node */
void insertAfter(struct Node* prev_node, int new_data, char *new_word)
{

    if (prev_node == NULL)
    {
      printf("the given previous node cannot be NULL");
      return;
    }

    struct Node* new_node =(struct Node*) malloc(sizeof(struct Node));

    new_node->data  = new_data;

    new_node->word= malloc(strlen(new_word));
    strcpy(new_node->word, new_word);

    new_node->next = prev_node->next;
    prev_node->next = new_node;
}


void append(struct Node** head_ref, int new_data, char *new_word)
{

    struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));

    struct Node *last = *head_ref;  


    new_node->data  = new_data;

    new_node->word= malloc(strlen(new_word));
    strcpy(new_node->word, new_word);

    new_node->next = NULL;


    if (*head_ref == NULL)
    {
       *head_ref = new_node;
       return;
    }


    while (last->next != NULL)
        last = last->next;


    last->next = new_node;
    return;
}



void deleteNode(struct Node **head_ref, char *word)
{

    struct Node* temp = *head_ref, *prev;
    if (strcmp(word, (*head_ref)->word)==0)
    {
        *head_ref = temp->next;   // Changed head
        free(temp);               // free old head
        return;
    }



    while (strcmp(word, (*head_ref)->word)!=0)
    {
        prev = temp;
        temp = temp->next;
    }

    if (temp == NULL) return;


    prev->next = temp->next;

    free(temp);  // Free memory

}

【问题讨论】:

    标签: c data-structures linked-list


    【解决方案1】:

    这部分看起来很奇怪:

    while (strcmp(word, (*head_ref)->word)!=0)
    {
        prev = temp;
        temp = temp->next;
    }
    

    strcmp 中使用head_ref,但在正文中更新temp 以移动到下一个元素。

    您是否打算这样做:

    while (strcmp(word, temp->word)!=0)
    {
        prev = temp;
        temp = temp->next;
    }
    

    还应该检查一下temp 是否为NULL。喜欢:

    while (temp && strcmp(word, temp->word)!=0)
    

    【讨论】:

    • 太棒了!一直都在我的眼皮底下,谢谢!
    【解决方案2】:

    除了@4386427 所说的,你没有为你的字符串分配足够的空间:

    new_node->word= malloc(strlen(new_word));
    

    请注意,C 库函数size_t strlen(const char *str) 计算字符串 str 的长度,但不包括终止空字符。所以我宁愿建议:

    new_node->word= malloc(strlen(new_word) + 1);
    new_node->word[strlen(new_word)] = '\0';
    

    这可能会导致您的内存出现一些问题。 ;)

    或者事件更好,使用calloc,这样第二行就不需要了:

    new_node->word= calloc(strlen(new_word) + 1, sizeof(char));
    

    【讨论】:

    • 我在其他数据结构中看到 +1 被使用,我一直不明白为什么,所以你澄清了我的疑问,谢谢!我将处理我的代码并对其进行编辑
    【解决方案3】:

    您的答案还可以,但仅作记录,经过足够的练习后,它应该看起来像这样:

    void deleteNode(struct Node **pplist, char *word)
    {
        for (struct Node *n = *pplist; n; n=*(pplist = &(n->next)))
        {
            if (!strcmp(n->word,word))
            {
                *ppnode = n->next;
                free(n->word);
                free(n);
                break;
            }
        }
    }
    

    关键是你可以只通过列表移动指向节点指针的指针,而不是将头部视为特殊情况。

    同样,你也可以这样追加:

    void append(struct Node** pplist, int new_data, char *new_word)
    {
        for(; *pplist; pplist=&((*pplist)->next));
        push(pplist, new_data, new_word);
    }
    

    insert_after(prev... 就是push(&(prev->next)...

    【讨论】:

      猜你喜欢
      • 2015-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-13
      • 2015-06-14
      • 1970-01-01
      相关资源
      最近更新 更多