【问题标题】:How to implement erase method in a doubly linked list如何在双向链表中实现擦除方法
【发布时间】:2014-01-31 23:57:55
【问题描述】:

我必须编写一个双向链表,我正在尝试实现erase(Type obj) 方法,该方法接受一个参数 obj 并遍历列表并删除具有元素 obj 的每个节点。

我面临的问题是,我从前面遍历链表,当我找到具有 obj 元素的节点时,我用 obj 元素更改节点之前和之后的节点的下一个/上一个指针.但是,我并没有删除带有 obj 本身的节点,据我所知 c++ 没有垃圾收集,因此具有 obj 的节点仍然悬在空中。如何删除?

我的擦除()

template <typename Type>
int Double_list<Type>::erase( Type const &obj ) {
if (empty()){
    return 0;
}
if (size() == 1 && head()->retrieve() == obj){
    list_head = nullptr;
    list_tail = nullptr;
    list_size--;
    return 1;
}

//Counter to hold the number of items deleted
int count = 0;
    //Iterating through the linked list
for (Double_node<Type> *ptr = head(); ptr != nullptr; ptr = ptr->next()){
    if (ptr->retrieve() == obj){
        ptr->previous_node->next_node = ptr->next();
        ptr->next()->previous_node = ptr->previous();
        count++;
        // delete ptr; // This stops me from iterating through the for loop
        list_size--;
    }
}
return count;
}

【问题讨论】:

  • 调整指针后,使用delete 关键字实际删除对象(释放它的内存)。
  • @ooga 如果我在更改 obj 节点之前和之后的节点指针之后执行delete ptr,那么我将无法再遍历链表。由于删除后我无法访问 ptr->next()
  • 首先你将前一个和下一个节点的指针设置为它的新值,然后然后delete被删除的节点......这是问题所在?
  • 但是您已经将 ptr->next() 复制到前一个节点的下一个指针!实际上,您只需复制并使用它即可。

标签: c++ erase doubly-linked-list


【解决方案1】:

当你遍历你的列表时,你正在使用指向类型为 Double_node&lt;Type&gt; * 的节点的指针来执行它,这意味着它被分配到某个地方并且可以用简单的 delete ptr 删除,但是因为你也使用它来获取列表中的下一个元素,你必须小心并过早记住它,所以它应该是这样的:

Double_node<Type> *ptr_next = 0;
for (Double_node<Type> *ptr = head(); ptr != nullptr; ptr = ptr_next) {
     ptr_next = ptr->next ();
     if (ptr->retrieve() == obj){
     if (ptr->previous_node)
       ptr->previous_node->next_node = ptr->next();

     ptr->next()->previous_node = ptr->previous();
     count++;
     list_size--;
     delete ptr;
    }

我相信这应该可以解决问题。

【讨论】:

  • This: ptr-&gt;previous_node-&gt;next_node 将调用 undefined behavior 如果正在寻找的节点原来是头节点,在这种情况下ptr-&gt;previous_nodeNULL。跨度>
  • @Predelnik 这仍然与我的问题相同。您可以删除指针delete ptr,但是您无法转到下一个节点,因为您正在使用这些指针遍历 for 循环
  • @AkshatAgarwal 你看我用ptr_next=ptr-&gt;next() 记住在下一次循环迭代中应该处理哪个节点,不管ptr 本身会发生什么。
【解决方案2】:

删除指针和对象时有一种语法叫做delete。 示例代码:

obj *temp = getCurrentNode();
//set pointers in nodes to the correct places
delete temp; //This releases all of the memory used in the object back to the OS
temp = NULL;//good practice to set this to null, since it points to non-allocated memory
//but exiting the function will make the pointer 'temp' useless, anyway.

【讨论】:

  • 正如我在第二条评论中提到的那样,如果我在更改 obj 节点之前和之后的节点指针之后确实删除了 ptr,那么我就无法再遍历链表了。由于删除后我无法访问 ptr->next()
  • 您将内存地址保存在临时指针中,如上所述,修复链接以忽略您正在删除的部分,并使用临时指针将其删除。这可以解决您更改链接后无法访问对象的问题,并且还允许您将内存中的对象空间释放回操作系统
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-10
  • 2019-11-23
  • 1970-01-01
  • 2012-03-23
  • 1970-01-01
  • 2021-11-18
相关资源
最近更新 更多