【问题标题】:Delete node from linked list (recursively)从链表中删除节点(递归)
【发布时间】:2012-12-06 13:47:49
【问题描述】:

!=我目前正在处理以下擦除递归布尔函数,该函数将 list 和 int 作为参数,如果找到并删除了 int,则返回 true,如果在列表中找不到它,则返回 false。它似乎工作,但问题是它删除了列表中的下一个int数,并且不是当前

 typedef struct E_Type * List;

 struct E_Type
 {
        int data;
        List next = 0;
 };

bool erase(const List & l, int data){
List current = l;   
if (current == 0)
{
   return false;
 }
else if (current->data == data)
{
      List deleteNode = new E_Type;
     deleteNode = current->next;//probably this causes the error, but how can I point it to the current without crashing the program
     current->next = deleteNode->next;
     delete deleteNode;
     return true;
}

else if (current->data != data)
{
      return erase(current->next, data);
}


}

【问题讨论】:

  • 可能不相关:List deleteNode = new E_Type; deleteNode = current->next;?这就是内存泄漏。
  • 另外一个不相关的评论:else if (current->data > data)的目的是什么?反正return语句是一样的。
  • 声明 if (current == 0) 将不起作用,除非 List 被 typedef 为指针类型,或者该类有一个重载的 == 运算符,该运算符采用指针/整数。跨度>
  • @Joachim 是的 List 是 typedef 指针指向 E_Type / R.Martinho 你是对的,我会修复这个泄漏,谢谢
  • 您的代码可能存在更多错误和问题,为什么不直接使用std::list(或者更好的是std::vector)?

标签: c++ linked-list


【解决方案1】:

列表有两种基本类型:

  • 单链表(每个节点都知道它的下一个节点)和
  • 双链表(每个节点都知道它的下一个节点以及它的前一个节点)。

如果像您的情况一样,有一个单链表,则不能检查 CURRENT 节点是否与“数据”相等,因为此时更改最后一个节点的下一个指针为时已晚。所以你总是要检查 NEXT 指针是否相等,像这样:

bool erase(const List & l, int data)
{
    List current = l;   
    if (current == 0)
        return false;

    // special case: node to be deleted is the first one
    if (current->data == data)
    {
        delete current;
        return true;
    }

    if (current->next && current->next->data == data) // next exists and must be erased
    {
        List deleteNode = current->next;   // Step 1: save ptr to next
        current->next = deleteNode->next;  // Step 2: reassign current->next ptr
        delete deleteNode;                 // Step 3: delete the node
        return true;
    }

    return erase(current->next, data);
}

注意:我忽略了你最后一个“else if”条件。 'else' 是因为前一个 if 在其中有一个 return,而 'if' 因为它的条件只是前一个 'if' 的否定,如果程序走到这一步 - 它将永远成立。

问候

【讨论】:

    【解决方案2】:

    您考虑的唯一节点是当前节点,因此您必须有修改l的规定:

    if (current->data == data)
    {
      l = current->next;
      delete current;
      return true;
    }
    

    【讨论】:

    • 那么他需要指向 l 的指针,而不是引用,但这应该可以工作。
    • @SvenS:不,l是指针,是通过引用传入的。
    • 啊,你是对的。这些年来,我仍然对那些东西感到困惑o_O
    • @SvenS,你并不孤单。函数指针仍然让我耳目一新。
    • 是的,这真的很混乱,而且像这样更复杂的函数的信息很少。您的建议有效,感谢@Beta
    【解决方案3】:

    这里有一些提示。

    一种迭代方法

    当您遍历列表时,仅维护一个指向 current 元素的指针是不够的。您还需要维护一个指向 previous 元素的指针,因为如果删除当前元素,则需要修复 previous->next

    除此之外,删除列表的第一个元素需要特殊处理。

    递归方法

    编写一个递归函数,该函数将获取指向列表头的指针,查找并删除所需元素,并返回指向新列表头的指针。为此,您需要:

    1. 定义和实现基本情况。处理单元素列表似乎是一种自然的选择。
    2. 定义递归。 有两种情况:要么列表的头部是您要查找的元素,要么不是。弄清楚在这两种情况下你需要做什么,然后从那里开始。

    【讨论】:

      【解决方案4】:

      如果您有清单:
      A --> B --> C --> D
      而你想删除 C,你必须:
      将 C 存储在临时变量中
      更改 B->next=C->next
      删除 C.
      所以你需要找到B才能修改它。
      您当然不应该创建任何 E_type 的新实例。

      【讨论】:

        【解决方案5】:

        你的情况

        else if (current->data == data)
        

        将在具有值数据的节点上停止。然后继续删除代码中此节点之后的节点。

        如果您想保持其余代码不变,那么该行应该是:

        else if ((current->next)->data == data)
        

        进行额外检查,以防第一个元素是列表中的唯一元素。

        更简单的方法是在当前元素之前保留一个指向该元素的指针,然后删除该指针所引用的节点。

        【讨论】:

          【解决方案6】:

          您需要更改前面的条目的next 指针。所以一切都找到了,但是您必须根据数据检查 current->next->data,而不是 current->data。

          如果 current 是列表中的最后一个条目,请务必检查 NULL 指针!

          【讨论】:

          • 如果列表中的第一个条目是应该删除的条目怎么办?
          • 也让我到了那里;) 正如 AshRJ 所写,您需要检查那个以及最后一个。
          【解决方案7】:

          当你从列表中删除一个节点时,你需要将前一个节点指向下一个节点。由于您有一个单链表,因此有 2 个选项:

          1. erase 函数中维护指向上一个 节点的指针。当遇到想要的节点时,将前一个节点链接到current->next 并删除当前节点。需要对列表中的第一个节点进行特殊处理。

          2. 遇到想要的节点,将current->next的内容复制到current,然后删除current->next。这样您的函数中就不需要额外的参数。需要对列表中的最后一个节点进行特殊处理。

          【讨论】:

          • 或者您可以将下一个节点的数据复制到当前节点并删除下一个节点
          • 还没想好,抱歉。
          • 编辑添加第二种方法。
          猜你喜欢
          • 2016-07-19
          • 1970-01-01
          • 2012-11-06
          • 1970-01-01
          • 2023-03-26
          • 2023-02-23
          • 1970-01-01
          • 2022-07-08
          • 2013-01-08
          相关资源
          最近更新 更多