删除单链表中的两个相邻节点

时间:2018-09-12 20:58:33

标签: c linked-list singly-linked-list

我是学生(还是新秀),我有问题。我必须删除单链列表中的一对节点,其总和等于 k 。 例如,如果链接列表为 13-> 4-> 5-> 4-> 3 k = 9 ,则我的函数应将列表转换为 13-> 3 (4 + 5 = 9,5 + 4 = 9)。这是我未完成的代码:

typedef struct _node
{
    int value;
    struct _node* next;
}Node;

void remove(Node **list, int k)
{
    if(*list == NULL || (*list)->next == NULL)
       return;

    Node *prev = *list;
    Node *tmp = (*list)->next;

    while(tmp != NULL)
    {
        if(prev->value + tmp->value == k)
        {
             free(prev);
             prev = tmp->next;
             free(tmp);
             tmp = tmp->next->next;
        }
    }
}

我有一个主意,但是我不知道如何在while循环中设置条件。 有人知道如何重写吗?

3 个答案:

答案 0 :(得分:1)

现在,您在第一个匹配项处断开链接:在您的示例中,删除4后,13的next仍指向该链接,并且一个悬空指针也是如此。但这不会发生,因为您永远不会从13移动到任何地方,因为您只会在删除一个元素时才向前迭代(这对13-> 4不会发生)。

您应该考虑的第三件事是,您应该实际标记要删除的元素,否则您将无法删除示例中的后四个元素。

答案 1 :(得分:0)

首先->您未在列表中前进,因此将导致无限循环。

第二个->如果tmp的下一个节点是NULL,则tmp=tmp->next->next会给您分段错误。

第三步->释放内存时,您也在中断链表,因此在基础代码中声明了pointToPrev指针,该指针指向prev后的节点指针,但在释放内存的情况下,它将指向网络节点tmp来保存列表。

更好地将while循环更改为此:

 `  int indicator=0;
    Node *pointToPrev = *list;
    if(prev->value + tmp->value == k)
    {
         *list=temp->next;
         free(tmp);
         free(prev);
         indicator=2;
    }
    while((tmp != NULL)&&(indicator!=2))
    {
          if(prev->value + tmp->value == k)
          {
             free(prev);
             pointToPrev->next = tmp->next;
             free(tmp)
             break; //AS YOU DON'T NEED TO COMPLETE THE ENTIRE WHILE LOOP AS SUM HAS BEEN ALREADY FOUND
          }
          else //THIS WILL SAVE YOU FROM THE INFINITE LOOP 
          {   
             tmp = tmp->next;
             prev = prev->next;
             if(indicator==0)
             {
                  pointToPrev = *list;
                  indicator=1;
             }
             else
                  pointToPrev=pointToPrev->next;
          }
    }

答案 2 :(得分:0)

以下事实使这个问题变得复杂:您有两个重叠的条件来控制是否应删除给定节点:如果其值与上一个节点的值之和是目标值,或者如果它与 next 节点的值之和是目标值。而且,除了当它是最后一个节点之外,您始终将下一个节点与下一个节点进行比较,因此,您必须纪念它所携带的值,否则必须避免删除它。

可以通过从第二个节点开始的普通链表遍历来解决此问题(或者,如果少于两个节点,则无需执行任何操作)。每次迭代

  • 确定当前节点和先前节点的节点值之和是否等于目标值
  • 如果是,则,如果在上一次循环迭代中该评估为真,则删除前一个节点

循环终止后,请删除最后一个节点(如果适用)。您需要在每次迭代之间携带足够的状态,以适当地执行删除操作,并记住上一次迭代中求和评估的结果,但是总的来说,这并不比按值删除单个节点困难得多。

这种方法非常简单,因为它将每次评估中必须考虑的案例数限制为两个,它永远不需要在列表中比下一个节点更进一步向前看,并且当删除一个节点时,该节点就是始终与当前节点具有相同的关系。该代码应保留为应做的练习。