web-dev-qa-db-ja.com

Cリンクリストからノードを削除します

リンクリストからノードを削除するにはどうすればよいですか?

これが私のコードです:

void RemoveNode(Node * node, Node ** head) {
    if (strcmp(node->state, (*(*head)->next).state) == 0) {
        Node * temp = *head;
        *head = (*head)->next;
        free(temp);
        return;
    }

    Node * current = (*head)->next;
    Node * previous = *head;
    while (current != NULL && previous != NULL) {
        if (strcmp(node->state, (*current->next).state) == 0) {
            Node * temp = current;
            previous->next = current->next;
            free(temp);
            return;
        }
        current = current->next;
        previous = previous->next;
    }
    return;
}

しかし、私はセグメンテーション違反を起こし続けています。

愚かなことをしているような気がします…何かアイデアはありますか?

7
Travv92

私の推測:

void RemoveNode(Node * node, Node ** head) {
    if (strcmp(node->state, ((*head)->state) == 0) {
        Node * temp = *head;
        *head = (*head)->next;
        free(temp);
        return;
    }

    Node * current = (*head)->next;
    Node * previous = *head;
    while (current != NULL && previous != NULL) {
        if (strcmp(node->state, current->state) == 0) {
            Node * temp = current;
            previous->next = current->next;
            free(temp);
            return;
        }
        previous = current;
        current = current->next;
    }
    return;
}
5
Jiminion

「ダブルポインタ」の必要性を回避するために、再帰を使用してこれを実行することをお勧めします。ロジックが非常に単純化されます。 このリンク これを再帰的に実行するための非常に優れた説明と実装があります。これは、空のリンクリストからノードを削除しようとした場合でも特に機能します。

Node *ListDelete(Node *currP, State value)
{
  /* See if we are at end of list. */
  if (currP == NULL)
    return NULL;

  /*
   * Check to see if current node is one
   * to be deleted.
   */
  if (currP->state == value) {
    Node *tempNextP;

    /* Save the next pointer in the node. */
    tempNextP = currP->next;

    /* Deallocate the node. */
    free(currP);

    /*
     * Return the NEW pointer to where we
     * were called from.  I.e., the pointer
     * the previous call will use to "skip
     * over" the removed node.
     */
    return tempNextP;
  }

  /*
   * -------------- RECURSION-------------------
   * Check the rest of the list, fixing the next
   * pointer in case the next node is the one
   * removed.
   */
  currP->next = ListDelete(currP->next, value);


  /*
   * Return the pointer to where we were called
   * from.  Since we did not remove this node it
   * will be the same.
   */
  return currP;
}
2
Tricky12