C++ 删除链接列表上的项目

C++ 删除链接列表上的项目,c++,linked-list,C++,Linked List,我已经实现了一个链表,但是我发现删除链表中的最后一个元素总是失败的。我检查了我的代码好几次,但没有发现逻辑错误。从头部和中间节点移除效果良好。下面是我的代码: #include<iostream> using namespace std; template<typename T> class Node{ // private: T val; Node *next; Node *prev; public: Node(T value){

我已经实现了一个链表,但是我发现删除链表中的最后一个元素总是失败的。我检查了我的代码好几次,但没有发现逻辑错误。从头部和中间节点移除效果良好。下面是我的代码:

#include<iostream>
using namespace std;
template<typename T>
class Node{ //
private:    
    T val;
    Node *next;
    Node *prev;
public:
    Node(T value){
        val = value;
        next = nullptr;
        prev = nullptr;
    }

    ~Node(){   
        if(prev != nullptr){
            prev->next = next;
        }
        if(next != nullptr){
            next->prev= prev;
        }
    }

    T& getVal(){  //
        return val;
    }

    Node* getNext(){
        return next;
    }

    Node* getPrev(){
        return prev;
    }

//insert node after this node
void insert(Node *n){
    if(next != nullptr){
        next->prev = n;
    }
    n->next = next;

    n->prev = this;
    next = n;
}

void deleteNode(){
    if(prev != nullptr && next != nullptr){
        prev->next = next;
        next->prev = prev;
        }
    }   
};

//build a linked list with deletion and push back function
template<typename T>
class LList{
private:
    Node<T> *head;
    Node<T> *tail;
public:
    LList(){
        head = nullptr;
        tail = nullptr;
    }

    ~LList(){
        if(nullptr != head){
            while(head->getNext() != nullptr){ //
                delete head->getNext();
            }
            delete head;
        }
    }



    void push_back(T val){  
        Node<T>* n = new Node<T>(val);
        if(head == nullptr){
            head = n ;
            tail = head;
        }
        else{
            tail->insert(n);
            tail = n;
        }
    }

    void deleteItem(T item){
        Node<T> *node = head;
        //delete head
        if(node->getVal() == item){
            head = node->getNext(); 
            node->deleteNode();
            return;
        }
        //delete middle and tail
        while(node->getVal() != item && node->getNext() != nullptr ){
        node = node->getNext();
        }

        if(node->getVal() == item && node == tail){
            tail = node->getPrev(); 
            node->deleteNode();
            return;
        }
        if(node->getVal() == item && node != tail){
            node->deleteNode();
            return;
        }
        else {
            cout<<"didnt find the item "<<item<<endl;

        }

    }

    void print(){
        Node<T> *node = head;
        while(node->getNext() != nullptr){
            cout<<node->getVal()<<endl;
            node = node->getNext();
        }
        cout<<node->getVal()<<endl;

    }
};


int main(){
    LList<double> list;
    list.push_back(3.13);
    list.push_back(2.8);
    list.push_back(23);
    list.push_back(4);
    list.print();
    list.deleteItem(3.13);
    list.deleteItem(2);
    list.deleteItem(4);
    list.print();
    return 0;
}
#包括
使用名称空间std;
模板
类节点{//
私人:
T值;
节点*下一步;
节点*prev;
公众:
节点(T值){
val=值;
next=nullptr;
prev=nullptr;
}
~Node(){
if(prev!=nullptr){
上一步->下一步=下一步;
}
如果(下一步!=nullptr){
下一步->上一步=上一步;
}
}
T&getVal(){//
返回val;
}
节点*getNext(){
下一步返回;
}
节点*getPrev(){
返回上一个;
}
//在此节点后插入节点
无效插入(节点*n){
如果(下一步!=nullptr){
下一步->上一步=n;
}
n->next=next;
n->prev=这个;
next=n;
}
void deleteNode(){
如果(上一个!=nullptr&&next!=nullptr){
上一步->下一步=下一步;
下一步->上一步=上一步;
}
}   
};
//建立具有删除和回推功能的链表
模板
类利斯特{
私人:
节点*头;
节点*尾部;
公众:
李斯特(){
水头=零PTR;
tail=nullptr;
}
~allist(){
if(nullptr!=头){
而(head->getNext()!=nullptr){//
删除head->getNext();
}
删除标题;
}
}
无效推回(T val){
节点*n=新节点(val);
if(head==nullptr){
水头=n;
尾=头;
}
否则{
尾部->插入(n);
尾=n;
}
}
无效删除项(T项){
节点*节点=头部;
//删除头
如果(节点->getVal()==项){
head=node->getNext();
节点->删除节点();
返回;
}
//删除中间和尾部
而(节点->getVal()!=项目和节点->getNext()!=nullptr){
node=node->getNext();
}
如果(节点->getVal()==项目和节点==尾部){
tail=node->getPrev();
节点->删除节点();
返回;
}
如果(节点->getVal()==项目和节点!=尾部){
节点->删除节点();
返回;
}
否则{
cout这里是:

void deleteNode(){
    if(prev != nullptr && next != nullptr){
        prev->next = next;
        next->prev = prev;
        }
    }   
};
对于最后一个元素,我猜
next
等于
nullptr
,因此整个条件失败。 我不明白的是,为什么删除第一个元素也不会失败,您可能应该对代码进行x检查

[编辑] 下面是我修复此错误的解决方案,它与节点的析构函数基本相同:

void deleteNode(){
    if(prev != nullptr){
        prev->next = next;
    } 

    if(next != nullptr){
        next->prev= prev;
    }
};
我认为所有案例都已在这方面得到考虑:

Head := prev == null & next->prev = nullptr (assuming prev for this node was nullptr before)
Middle := prev->next = next & next->prev = prev
Tail := prev->next = null (assuming as above) & next == null
Head&Tail := prev == null & next == null (Only element of the list is deleted, so no references to be changed)

[/编辑]

这解释了删除最后一个节点失败的原因;新的最后一个剩余节点有一个悬空的
next
指针,它仍然指向失效的节点。在删除第一个节点的情况下,同样的错误也会发生——新的第一个节点有一个悬空的
prev
指针——但是没有人经常使用该指针。现在您已经找到了bug,我建议您编辑您的答案以显示如何更正。如果您使用sentry节点,则没有特殊情况。请参阅