C-单个链接列表中只有1个元素时删除节点

时间:2018-11-07 13:50:41

标签: c nodes singly-linked-list

大家好,我知道要删除链接列表中有多个元素的节点,请从当前节点中删除要删除的前一个节点,并将其指向current->next,然后{{ 1}}当前节点。

但是我的问题是,当我在一个链表中只有一个元素时,当我尝试删除该节点时,似乎出现了分段错误(核心转储),我认为这是因为在这种情况下,{{1 }}指向free()(我在这里可能是错误的)。还可以说我有一个存储值为5的节点,我遇到的一个常见问题是不是删除该节点,而是将其值更改为0。

问题: 我没有要求任何人修复我的代码,这就是为什么我决定不发布代码,但是我的问题是,当该节点是链表中的唯一元素时,我将如何处理该节点?与删除多个元素时,如何删除链表中只有一个元素的节点不同。

非常感谢您的帮助,如果事情不清楚,我们深表歉意,但是我真的想在提出问题之前先给出具体背景。

6 个答案:

答案 0 :(得分:0)

在链表中,可以用不同的方法删除节点。

A)删除第一个节点

算法:

Step1: temp = head
Step2: temp = temp->next
Step3: free(temp)
Step4: head = NULL

B)删除最后一个节点

算法

Step1: p = head
Step2: while p->next->next != NULL 
         p = p->next
Step3: temp = p->next
Step4: p->next = NULL
Step5: free(temp)

C)删除中间的节点。

算法:

Step1: p = head
Step2: while POSITION > 2 #Indexing from 1
         p = p->next
         POSITION = POSITION - 1
Step3: temp = p->next
Step4: p->next = p->next->next
Step5: free(temp)

答案 1 :(得分:0)

您的“链接列表”只是列表中第一个元素的指针。

MyStruct *my_list;

因此,如果my_list-> next为null,则意味着列表中只有一个元素。 如果要删除他,这很简单:

free(my_list)
my_list = NULL;

您的列表现在为空(请勿尝试阅读此内容;))

答案 2 :(得分:0)

从列表中删除元素时,有两种特殊情况需要担心:第一个元素和最后一个元素,有时它们是同一元素。

两者都可以这样处理:

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

void deleteNode(node **head, int value) {
    node *prev = NULL, *curr = *head;

    // look for the node to delete
    while (curr && curr->value != value) {
        prev = curr;
        curr = curr->next;
    }

    if (curr == NULL) {
        printf("node to delete not found\n");
    } else if (prev == NULL) {
        // need to delete the first node, so repoint head to next node
        *head = (*head)->next;
    } else {
        // deleting an internal node, so have the previous point to the current's next
        prev->next = curr->next;
    }
    // no need to check for the last node 
    // since we're copying next which may or may not be NULL

    free(curr);
}

答案 3 :(得分:0)

这完全取决于您对链表的实现。

一些可能的实现方式。

  • 带有外部指针的线性链接列表,用于启动节点
    • 如果为空,则指向NULL
    • 最后一个节点为空
  • 圆形链接列表,带有指向起始节点的外部指针
    • 如果只有一个元素,它将指向自身,而外部元素则指向唯一的元素
    • 如果没有元素,则外部指针为NULL
  • 以一个元素为首元素的圆形链表
    • 如果元素为空,则指向自身
  • 封装成结构
    • 上述链接方案之一
    • 带有附加的结束指针,可以更快地插入结束

根据列表的结构,实现可能会有所不同。

一般来说,您可以从指针H开始,该指针指向元素E,并且该元素具有指向后继{{1}的指针next }。

您正确的将S设置为H的内容。由于nextH必须有效,因此不会出现分段错误。

以最简单的形式(未经检查/未经编译的代码-应该只显示原理):

E

考虑以下列表。

typedef struct ListNode{
  void* data,
  struct ListNode* next;
}ListNode;

/**
  *  \brief  removes an element from the linked list 
  *
  *  \param  io_el  the 'next' pointer of the previous 
  *                 element or the pointer to the head
  *  \return the pointer to the removed element
  *  
  *  \details
  *  uses the io_el pointer to advance to the next list element and 
  *  sets the io_el pointer to the content of the next pointer of
  *  this element. This effectivly removes the element from the chain.
  *  The removed element is returned so that it may be free'd if necessary. 
  */
Node* ListDeleteElement(Node** io_el){
  Node* res = NULL;
  if( io_el && *io_el){
    res = *io_el;
    *io_el = (*io_el)->next;
  }
}

此实现有点危险-传递的指针绝对是指向列表实际元素的head指针或指向Node E1 ,E2,E3; Node* H = &E1; E1.next = &E2; E2.next = &E3; E3.next = NULL; // (H = ) E1 -> E2 -> E3 -> NULL // remove E3; ListDeleteElement( &(H->next->next) ); // passes pointer to the nextpointer of E2, // E2.next should be NULL now // (H = ) E1 -> E2 -> NULL // remove E1 ListDeleteElement( &H ); // *H should now be E2 // (H = ) E2 -> NULL // again remove first element ListDeleteElement( &H ); // (H = ) NULL 指针的指针。

将任意指针的地址传递到列表结构中会损坏列表。

因此,该代码应用作内部帮助程序函数,该函数由一些更高级的函数包装,或者应在较小的本地列表中使用,因为它们不会传递给其他程序部分。在这种情况下,我将设计一个更强大的列表类。

答案 4 :(得分:0)

删除不是第一个节点的节点时,步骤是

1)previous_node->next = node_to_delete->next;

2)free(node_to_delete)

当删除的第一个节点时,您跳过步骤1 ,因为没有previous_node。相反,您必须像这样更新列表的开头:

3)head = node_to_delete->next;

这可以通过多种方式实现。例如:

node* delete(node* head, int n)
{
    node* prev = NULL;
    node* temp = head;

    while (temp)
    {
        if (temp->value == n) 
        {
            if (prev)
            {
                // All except first node
                prev->next = temp->next;
            }
            else
            {
                // First node
                head = temp->next;
            }
            free(temp);
            return head;
        }
        prev = temp;
        temp = temp->next;
    }

    return head;
}

并这样称呼它:

head = delete(head, 42);

答案 5 :(得分:0)

1:如果元素是头部。

   nodeptr deleteBeginning(nodeptr head){
        nodeptr current = head;
        head= head->next;
        free(current);
        return head;
   }

2:对于其余元素。

   nodeptr deleteNode(nodeptr head, int value){
    if(value == head->data) {
        head = deleteBeginning(head);
        return head;
    }

    nodeptr current = head;
    nodeptr previous;

    while(current->data != value){
        previous = current;
        current = current->next;
    }

    previous->next = current->next;
    free(current);
    return head;
   }

nodeptr只是结构Node *的typedef