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



我是学生(还是菜鸟),我有一个问题。我必须删除单向链表中的一对节点,其总和等于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 的next仍然指向它,悬空的指针也是如此。但这不会发生,因为你永远不会从 13 移动到任何地方,因为只有当你删除一个元素时,你才会向前迭代(这对 13->4 对不会发生)。

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

First --> 您没有在列表中前进,因此将导致无限循环。

第二 --> 如果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;
}
}

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

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

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

循环终止后,根据需要删除最后一个节点。 您需要在迭代之间携带足够的状态,以便适当地执行删除并记住上一次迭代中求和计算的结果,但总的来说,这并不比按值删除单个节点困难多少。

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

相关内容

  • 没有找到相关文章

最新更新