【问题标题】:Deleting two adjacent nodes in singly linked list删除单链表中的两个相邻节点
【发布时间】:2019-02-17 13:55:22
【问题描述】:

我是学生(还是个菜鸟),我有一个问题。我必须删除单链表中的一对节点,其总和等于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 循环中设置条件。 有谁知道如何重写这个?

【问题讨论】:

  • 欢迎来到 SO。你的要求有点不清楚。您是否必须删除成对的数字或任何可以与任何其他数字配对以匹配k 的数字? 4->5->4 部分不是一对或两对。删除第一对 4->5 后,没有更多的对要删除。根据您的目标,代码看起来会非常不同。

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


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    首先 --> 你没有在列表中前进,因此它会导致无限循环。

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

    【讨论】:

    • 这是我得到的:[13, 0, -2069100912, 4, 3]。第一个 if 部分肯定有问题:/
    • @Filip 这是你的意见吗?
    • 这是一个输出。
    • @Filip 您是否看到我的回答中如何以及为什么修改了while 循环?你换了吗?
    • @Filip 再次修改,立即尝试!
    【解决方案3】:

    这个问题很复杂,因为你有两个重叠的条件来控制是否应该删除给定节点:如果它的值与 previous 节点的值之和是目标值,或者如果它的值与 next 节点的总和是目标值。更重要的是,除了当它是最后一个节点时,你总是需要将下一个节点与它后面的一个节点进行比较,所以要么你必须记住它所携带的值,要么你必须避免删除它。

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

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

    循环终止后,如果合适,删除最后一个节点。您需要在每次迭代中携带足够的状态以适当地执行删除并记住上一次迭代中求和的结果,但总体而言,这并不比按值删除单个节点困难多少。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      • 1970-01-01
      • 2020-08-11
      • 1970-01-01
      • 2020-02-04
      相关资源
      最近更新 更多