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

C 删除单链表中的两个相邻节点,c,linked-list,singly-linked-list,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 || (*lis

我是一名学生(还是新手),我有一个问题。我必须删除单链表中的一对节点,它们的和等于k。 例如,如果链接列表是13->4->5->4->3k=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循环中设置条件。
有人知道如何重写吗?

现在,您在第一次匹配时就断开了链接:在您的示例中,删除4后,13的
下一个
仍然指向它,还有一个悬空的指针。但是它不会发生,因为你永远不会从13移动到任何地方,因为你只会在删除一个元素时向前迭代(这对于13->4对来说是不会发生的)

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

First-->您没有在列表中向前移动,因此它将导致无限循环

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

第三-->当您释放内存时,您也在破坏链表,因此在基础代码中声明了
pointToPrev
指针,它将指向
prev
指针后面的节点一,但如果在内存中释放,它将指向net node to
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;
          }
    }

由于有两个重叠的条件控制是否应删除给定节点,因此此问题变得复杂:其值与前一个节点值之和是否为目标值,或其值与下一个节点值之和是否为目标值。更重要的是,除非它是最后一个节点,否则您将始终需要将下一个节点与它后面的节点进行比较,因此您必须记住它所承载的值,否则必须避免删除它

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

  • 确定当前和以前节点的节点值之和是否等于目标值
  • 如果是这样,或者如果在上一个循环迭代中该计算为真,则删除上一个节点
循环终止后,如果合适,删除最后一个节点。您需要在一个迭代到另一个迭代之间携带足够的状态,以便适当地执行删除操作,并记住上一个迭代中求和计算的结果,但总的来说,这并不比按值删除单个节点困难多少


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

下面是我得到的:[13,0,-2069100912,4,3]。第一个if部分肯定有问题:/@Filip是您的输入吗?它是一个输出。@Filip在我的答案中修改了
循环时,您看到了
的方式和原因了吗?你换了你的吗?@Filip再次修改,现在再试一次!欢迎来到SO。你的要求有点不清楚。您是否必须删除成对的数字或任何可以与任何其他数字配对以匹配
k
?零件
4->5->4
不是一对或两对。删除第一对
4->5
后,没有更多的对可删除。根据您的目标,代码看起来会非常不同。