使用迭代器删除 doublearrayList 的最后一个节点

Posted

技术标签:

【中文标题】使用迭代器删除 doublearrayList 的最后一个节点【英文标题】:Delete the last node of a doublyarrayList with an iterator 【发布时间】:2022-01-09 10:57:51 【问题描述】:

当我调用remove() 时,我正在尝试删除最后一个节点,而我的当前节点位于最后一个节点。

每次我尝试删除最后一个节点时,我的当前和最后一个节点应该是新的最后一个节点。但是,相反,我的最后一个节点被删除了。

有人可以用一个例子来解释我应该怎么做吗?

我可以使用这些方法获取第一个和最后一个节点Node<TYPE>* getLast()

这是我从现在开始的错误代码:

Node<TYPE>* elementToDelete = currentNode;
this->currentNode = currentNode->getPrevious();

Node<TYPE>* newLastNode = currentNode;
Node<TYPE>* nullLastNode = list->getLast()->getNext();
list->getLast()->getPrevious()->setNext(newLastNode);
            
newLastNode->setNext(nullLastNode);
            
delete elementToDelete;
list->decreaseSize();

我的清单

#pragma once
#include "List.h"
#include "Node.hpp"

template <class TYPE>
class DoubleLinkedList : public List<TYPE>

public:
    DoubleLinkedList()
    
        this->first = nullptr;
        this->last = nullptr;
        this->nbElements = 0;
    

    ~DoubleLinkedList()
    
        while (!isEmpty())
            pop();
    

    void push(const TYPE& content) override
    
        Node<TYPE>* newNodeAdded = new Node<TYPE>(content);
        //Si vide
        if (this->last == nullptr)
        
            this->last = newNodeAdded;
            this->first = last;

            //C'est le seul endroit ou on va ajouter les deux nodes spéciaux
            this->last->setPrevious(new Node<TYPE>(BOFile, true));
            this->last->getPrevious()->setNext(last);

            this->last->setNext(new Node<TYPE>(EOFile, true));
            //fin ajout nodes spéciaux
        
        //Sinon fin
        else
        
            newNodeAdded->setNext(last->getNext());
            newNodeAdded->setPrevious(this->last);

            //Gestion d'un node spécial
            this->last->setNext(newNodeAdded);

            this->last = this->last->getNext();
        

        this->last->getNext()->setPrevious(last);
        enlargeSize();
    

    void pop() override
    
        if (isEmpty()) throw EmptyListException();

        Node<TYPE>* temp = this->first;
        this->first = temp->getNext();
        //Si dernier element
        if (temp == this->last)
        
            this->last = nullptr;

            //on pop le dernier node alors on efface les deux nodes spéciaux
            delete temp->getNext();
            delete temp->getPrevious();
            //fin gestion effacement
        
        //Sinon
        else
        
            //Avant c'était setPrevious(nullptr);  Maintenant on gère les nodes spéciaux
            this->first->setPrevious(temp->getPrevious());
            this->first->getPrevious()->setNext(first);
        
        delete temp;
        decreaseSize();
    

    TYPE& front() override
    
        if (isEmpty()) throw EmptyListException();

        return *first->getContent();
    

    TYPE& back() override
    
        if (isEmpty()) throw EmptyListException();

        return *(last->getContent());
    

    bool isEmpty() const
    
        return this->nbElements == 0;
    

    void enlargeSize() 
    
        this->nbElements++;
    

    void decreaseSize() 
    
        this->nbElements--;
    

    int size() const override
    
        return this->nbElements;
    

    Node<TYPE>* getFirst()
    
        if (isEmpty()) throw EmptyListException();

        return first;
    

    Node<TYPE>* getLast()
    
        if (isEmpty()) throw EmptyListException();

        return last;
    

private:
    Node<TYPE>* first;
    Node<TYPE>* last;
    int nbElements;
;


我的节点

#pragma once
static const int BOFile = -1;
static const int EOFile = 1;

template <class TYPE>
class Node

public:
    Node(const TYPE& content)
    
        setContent(content);
        this->next = nullptr;
        this->previous = nullptr;
        this->extremityStatus = 0;
    

    Node(int extremityStatus, bool failsafe)  //Le booléen est parce que si le template est int la signature devient ambigue
    
        content = nullptr;
        this->next = nullptr;
        this->previous = nullptr;
        this->extremityStatus = extremityStatus;
    

    ~Node()
    
        if (content != nullptr)
            delete content;
    

    Node* getNext()
    
        return next;
    

    void setNext(Node* next)
    
        this->next = next;
    

    Node* getPrevious()
    
        return previous;
    

    void setPrevious(Node* previous)
    
        this->previous = previous;
    

    TYPE* getContent()
    
        return content;
    

    void setContent(const TYPE& content)
    
        this->content = new TYPE(content);
    

    bool isBOFNode()
    
        return extremityStatus == BOFile;
    

    bool isEOFNode()
    
        return extremityStatus == EOFile;
    

private:
    Node* next = nullptr;
    Node* previous = nullptr;
    TYPE* content = nullptr;
    int extremityStatus = 0;
;

【问题讨论】:

您的代码显示得还不够多。我们不知道您是如何实现各种成员函数的,我们不知道您的Node 类型是什么样的,也不知道list 是否也是Node 或它自己的结构。我看到的主要事情是缺乏 NULL 测试,这可能重要也可能不重要,具体取决于导致您显示的代码位的先决条件。 我认为你有点过于复杂了。绘制一个小列表的图片,然后在您逐个链接删除要删除的节点时重绘该列表。 @paddy 这里是我的所有课程,我无法更改 push 或 pop,所有内容都需要在 remove 和 insert 中进行 remove 和 insert 如果NodeList 声明为朋友,该程序将不那么冗长并且具有更紧密的封装。这是friend 的适当用法,因为这些类具有功能耦合。在节点上设置链接指针的公共方法是不合适的,不应公开。 “extremityStatus”也令人费解。它似乎根本不属于该节点。这种事情应该与列表维护无关,并且最好由任何需要它的列表用户与结构捆绑。 什么是“双重数组列表”?你说的是一个双向链表数组吗?你是在说一个像数组一样的双向链表吗? 【参考方案1】:

currentNode 指向最后一个节点时,您需要告诉list 更新其last 指针,但您的代码并未尝试这样做。如果 list 中只有 1 个节点,您也不会更新 listfirst 指针,因此您实际上是在使列表为空。

当从双链表中删除 any 节点时,您可以使用更像这样的逻辑:

Node<TYPE>* elementToDelete = currentNode;
currentNode = elementToDelete->getNext();

if (elementToDelete->getNext())
    elementToDelete->getNext()->setPrevious(elementToDelete->getPrevious());

if (elementToDelete->getPrevious())
    elementToDelete->getPrevious()->setNext(elementToDelete->getNext());

if (list->getLast() == elementToDelete)
    list->setLast(elementToDelete->getPrevious());

if (list->getFirst() == elementToDelete)
    list->setFirst(elementToDelete->getNext());

delete elementToDelete;
list->decreaseSize();

如果您知道currentNode 是最后一个节点,那么实际上是这样的:

Node<TYPE>* elementToDelete = ...;
currentNode = nullptr;

if (elementToDelete->getPrevious())
    elementToDelete->getPrevious()->setNext(nullptr);

list->setLast(elementToDelete->getPrevious());

if (list->getFirst() == elementToDelete)
    list->setFirst(nullptr);

delete elementToDelete;
list->decreaseSize();

话虽如此,这种逻辑确实属于您的 list 类的方法,而不是迭代列表的外部代码。

【讨论】:

我不明白 (elementToDelete->getNext())。这是什么意思? 它正在做一个空测试。非空值的计算结果为true,空值的计算结果为false 对不起,我在课堂上没看到。我这几个月才学这门语言 @NicolasPellerin if (elementToDelete-&gt;getNext()) 在这种情况下是 if (elementToDelete-&gt;getNext() != nullptr) 的简写

以上是关于使用迭代器删除 doublearrayList 的最后一个节点的主要内容,如果未能解决你的问题,请参考以下文章

使用迭代器 C++ 删除对象类型的向量元素

为啥迭代器指向的数据在从列表中删除后保留

仅通过迭代器删除 STL 容器元素

java中的迭代器 - 删除范围内的数字

map在遍历中删除元素,避免迭代器失效

STL 中 使用迭代器删除元素的问题