链表:当值不在列表中时,remove()和search()方法无法正常工作 >我试图在C++中创建模板链接列表类。除了我对不在链接列表中的值调用这两个方法外,所有方法都工作得很好,包括所讨论的remove()和search()。理想情况下,我希望这些方法在发现值不在列表中后返回,但是,我觉得这些方法会继续,并尝试进一步删除或搜索某个值,因为当我运行可执行文件时,会出现“Segementation Fault(core dumped)”错误。如果在空列表中调用方法,程序将打印正确的错误

链表:当值不在列表中时,remove()和search()方法无法正常工作 >我试图在C++中创建模板链接列表类。除了我对不在链接列表中的值调用这两个方法外,所有方法都工作得很好,包括所讨论的remove()和search()。理想情况下,我希望这些方法在发现值不在列表中后返回,但是,我觉得这些方法会继续,并尝试进一步删除或搜索某个值,因为当我运行可执行文件时,会出现“Segementation Fault(core dumped)”错误。如果在空列表中调用方法,程序将打印正确的错误,c++,linked-list,C++,Linked List,列表与头单独链接,并使用“智能节点”实现(即包含自己的方法以补充匹配类方法的节点,而不是不包含方法且需要类方法创建指向节点的临时指针并在列表中迭代的“哑节点”) 下面是search()和remove()的实现。当然,如果需要,我可以提供更多代码: //==========================REMOVE================================ template <class T> void TLinkedList<T> :: remo

列表与头单独链接,并使用“智能节点”实现(即包含自己的方法以补充匹配类方法的节点,而不是不包含方法且需要类方法创建指向节点的临时指针并在列表中迭代的“哑节点”)

下面是search()和remove()的实现。当然,如果需要,我可以提供更多代码:

//==========================REMOVE================================

template <class T>
void TLinkedList<T> :: remove(T value){
  if(!head){                               //if there is no head
    std::cerr << "Error: List is Empty" << std::endl;  // The list is empty
    return;
  }
  if(head->data == value){
    listSize--;     //decremenets listSize since a node is removed
    node * temp = head;
    head = head->next;
    delete head;
    return;
  }
  else{
    if(head->remove(value)){  //If something was removed as a result of the node's remove()
      listSize--;
      return;                 //decrement listSize since something was removed
    }
    else{                     //else if nothing removed
      std::cerr << "Error : Value not in list" << std::endl;
      return;
    }
  }
}

template <class T>
bool TLinkedList<T> :: node :: remove(T value ){  //returns a bool. If something was removed, returns true. If nothing was removed, returns false
  if(next-> data == value){
    node * temp = next;
    next = next->next;
    delete temp;
    return true; //something removed
  }
  if(!next){
    return false;
  }
  else{
    return next -> remove(value);
  }
}


//==============SEARCH===================
template <class T>
T TLinkedList<T> :: search(T value){
   if(!head){
    std::cerr << "Error: List is empty" << std::endl;
    return 0;
  }
  if(head->data == value){  //If head's data is the value searched for
    return head->data;      //return head's data
  }
  else{
    return head->search(value);
  }

}

template <class T>
T TLinkedList<T> :: node :: search(T value){
  if(data == value){
    return data;
  }
  if(!next){
    std::cerr << "Error: Value not in list" << std::endl;
    return 0;
  }
  else{
    return next->search(value);
  }
}
cerr没有发生,并且给出了“分段故障(堆芯转储)”错误

非常感谢您的帮助。谢谢


编辑:另外,在search()方法中,您可能会注意到我返回0;当发生错误时。此实现是在遇到错误时尝试停止该方法;理想情况下,如果遇到错误,我希望搜索不返回任何内容。让我们从您的方法删除包含几个错误开始。首先考虑方法<代码>无效TLIKEDLIST::移除(t值);<代码> 在此代码段中,删除列表的标题

  if(head->data == value){
    listSize--;     //decremenets listSize since a node is removed
    node * temp = head;
    head = head->next;
    delete head;
    return;
  }
一定是

  if(head->data == value){
    listSize--;     //decremenets listSize since a node is removed
    node * temp = head;
    head = head->next;
    delete temp; // <==
    return;
  }
当fro方法搜索时,我将用以下方式定义它们

template <class T>
TLinkedList<T>::node * TLinkedList<T>::search( const T &value ) const
{
    return ( head == nullptr ? nullptr : head->search( value ) );
}

template <class T>
TLinkedList<T> :: node * TLinkedList<T>::node::search( const T &value ) const
{
   if ( data == value ) return this;

   return  ( next == nullptr ? nullptr : next->search( value ) );
}
模板
TLinkedList::节点*TLinkedList::搜索(常量T和值)常量
{
返回(head==nullptr?nullptr:head->search(value));
}
模板
TLinkedList::node*TLinkedList::node::search(const T&value)const
{
如果(数据==值)返回此值;
返回(next==nullptr?nullptr:next->search(value));
}

根据我上面的评论,这是您的搜索功能的外观:

//==============SEARCH===================
template <class T>
T TLinkedList<T>::search(T value){
    if(!head){
        std::cerr << "Error: List is empty" << std::endl;
        return 0;
    }
    else if(head->data == value){  //If head's data is the value searched for
        return head->data;      //return head's data
    }

    typename TLinkedList<T>::node *temp = head->search(value);
    if (temp)
        return temp->data;
    return 0;
}
/===================搜索===================
模板
T TLinkedList::搜索(T值){
如果(!头){
标准::cerr搜索(值);
如果(临时)
返回温度->数据;
返回0;
}
节点::搜索

template <class T>
typename TLinkedList<T>::node *TLinkedList<T> :: node:: search(T value) {
    if(data == value){
        return this;
    }
    else if(!next){
        std::cerr << "Error: Value not in list" << std::endl;
        return nullptr;
    }
    return next->search(value);
}
模板
typename TLinkedList::node*TLinkedList::node::search(T值){
如果(数据==值){
归还这个;
}
否则如果(!下一步){
标准::cerr搜索(值);
如果(tmp!=nullptr){
listSize--;//自删除节点后减小listSize
节点*tmp2=tmp;
tmp=tmp->next;
删除tmp2;
}

else std::cerr代码在几个地方被破坏。以下是我发现的:

  • 如果要删除第一个节点,则会删除新的头而不是第一个节点。您可能打算使用

    delete temp;
    
    而不是

    delete head;
    
  • 如果列表中只有一个节点与该值不匹配,则
  • 函数将访问一个不存在的节点。您需要检查
    next
    是否指向某个对象或访问其值。实际上,由于列表最终只包含一个元素的尾部,这就解释了一个崩溃。您可能希望

    if (!next) { /* error goes here */ }
    else if (next->value == value) { /* successful return goes here */ }
    else { /* recursion goes here */ }
    
  • …::node::search()
    函数也有同样的问题,解释了您的另一次崩溃。不过,该函数似乎有一个毫无意义的界面:您搜索一个值,如果找到一个值,则返回搜索值。否则返回
    0
    ,这意味着所有类型
    T
    都可以与
    搜索()一起使用
    方法需要有一个接受
    0
    的构造函数。这似乎是一个相当苛刻的限制。您可能希望将迭代器返回到找到的对象,或将迭代器返回到列表的末尾


  • 注意到,在C++中,管理列表的递归方法不太好。函数的编写方式允许尾部递归,但我不认为C++有任何尾部回溯实际上被实现的安全性,即,在遍历长列表时,可以很容易地完成堆栈空间。它来自于您的

    prepend()
    方法。此外,正如其他人在文章中所说,您的实现缺乏检查和安全性


    为什么不使用已经存在并满足一般用途的
    STL
    Boost
    链表?

    您应该让搜索功能返回包含正在搜索的元素的节点,或者如果未找到该元素,则返回
    nullptr
    。然后,您的删除操作将调用搜索,然后删除该元素T
    //==========================REMOVE================================
    
    template <class T>
    void TLinkedList<T> :: remove(T value){
        if(!head) {                               //if there is no head
            std::cerr << "Error: List is Empty" << std::endl;  // The list is empty
            return;
        }
        else if(head->data == value){
            listSize--;     //decremenets listSize since a node is removed
            node *tmp = head;
            head = head->next;
            delete tmp;
            return;
        }
    
        node *tmp = head->search(value);
    
        if (tmp != nullptr) {
            listSize--;     //decremenets listSize since a node is removed
            node *tmp2 = tmp;
            tmp = tmp->next;
            delete tmp2;
        }
        else std::cerr << "Error : Value not in list" << std::endl;
    }
    
    delete temp;
    
    delete head;
    
    if (!next) { /* error goes here */ }
    else if (next->value == value) { /* successful return goes here */ }
    else { /* recursion goes here */ }