在尝试删除头部时意外删除整个链表

时间:2013-10-19 01:39:43

标签: visual-c++ singly-linked-list

我正在为我的C ++课程制作一个检查器的模拟游戏。我的问题在于包含检查器的链表。我可以完美地删除任何检查器,但列表的头部除外。我在这里和其他网站环顾四周,我相信某处有内存泄漏。我对C ++很陌生,所以我不确定除了玩弄东西之外该做什么(这可能会产生更大的问题)。我以前从未在这里发帖,所以请原谅我,如果格式有点偏或太乱。我会尽量简短。首先,这是链表的节点类的片段。

class CheckerpieceNode 
{
private:
    Checkerpiece *Node;
    CheckerpieceNode *Next;
public:
    CheckerpieceNode(); // sets Node and Next to NULL in .cpp file
    void setNode(Checkerpiece *node);
    void setNext(CheckerpieceNode *next);
    Checkerpiece* getNode();
    CheckerpieceNode* getNext();
}; 

这些功能的设置与Checkerpiece.cpp类中的功能非常相似。 以下是代码的使用方法。它由我的主类中的Checkerboard对象调用。

 theCheckerboard.removeChecker(theCheckerboard.findChecker(selector->getCurrentX() + 0, selector->getCurrentY() - VERTICAL_SHIFT, listHead), listHead);

VERTICAL_SHIFT只与我的棋盘图形在控制台上的方式有关。由于它适用于所有其他节点(不包括头部),因此我将其排除为错误源。选择器是一个检查对象,但它不是列表的一部分。

这是Checkerboard类中的实际findChecker和removeChecker代码。

Checkerpiece* findChecker(int x, int y, CheckerpieceNode* list_head)
{
if(list_head== NULL) return NULL; // do nothing
else
{
    CheckerpieceNode* node = new CheckerpieceNode;
    node = list_head;
    while(node != NULL && node->getNode() != NULL)
    {
        if()// comparison check here, but removed for space
        {
            return node->getNode(); 
            delete node; 
            node = NULL;
        }
        else // traversing
            node = node->getNext();
    }

    return NULL; 
}
}


void removeChecker(Checkerpiece* d_checker, CheckerpieceNode* list_head)
{
if(list_head== NULL) // throw exception
else
{
    CheckerpieceNode *temp = NULL, *previous = NULL;
    Checkerpiece* c_checker= new Checkerpiece;
    temp = list_head;
    while(temp != NULL && temp->getNode() != NULL)
    {
        c_checker= temp->getNode();
        if(d_checker!= c_checker) 
        {
            previous = temp;
            temp = temp->getNext();
        }
        else
        {
            if(temp != list_head)
            {
                previous->setNext(temp->getNext());
                delete temp;
                temp = NULL;
            }
            else if(temp == list_head) // this is where head should get deleted
            {   
                temp = list_head;
                list_head= list_head->getNext();
                delete temp;
                temp = NULL;
            }


            return;
        }
    }
}
}

3 个答案:

答案 0 :(得分:0)

removeChecker无法修改list_head的值,因为它已超过值。方法签名应为:

void removeChecker(Checkerpiece* d_checker, CheckerpieceNode** list_head)
// You will need to call this function with &list_head

void removeChecker(Checkerpiece* d_checker, CheckerpieceNode* &list_head)
// Calling code does not need to change

答案 1 :(得分:0)

哦,我的,你让它复杂化了。大量冗余检查,分配和不必要的变量(如c_checker也会泄漏内存)。

// Write down the various scenarios you can expect first:
// (a) null inputs
// (b) can't find d_checker
// (c) d_checker is in head
// (d) d_checker is elsewhere in the list
void removeChecker(Checkerpiece* d_checker, CheckerpieceNode* list_head) {
   // first sanitize your inputs
   if (d_checker == nullptr || list_head == nullptr) // use nullptr instead of NULL. its a keyword literal of type nullptr_t
       throw exception;

   // You understand that there is a special case for deleting head. Good.
   // Just take care of it once and for all so that you don't check every time in the loop.
   CheckerpieceNode *curr = list_head;

   // take care of deleting head before traversal
   if (d_checker == curr->getNode()) {
       list_head = list_head->next; // update list head
       delete curr; // delete previous head
       return; // we're done
   }

   CheckerpieceNode *prev = curr;
   curr = curr->next;

   // traverse through the list - keep track of previous
   while (curr != nullptr) {
       if (d_checker == curr->getNode()) {
           prev->next = curr->next; 
           delete curr;
           break;    // we're done!
       }

       prev = curr;
       curr = curr->next;
   }
}

我希望有所帮助。花点时间将问题分解成更小的部分,找出可能的情况,如何处理它们,然后才开始编写代码。

答案 2 :(得分:0)

根据问题作者的this edit,他使用的解决方案是:

  

我修改了代码以显示检查器删除中传递的地址   功能。

void delete_checker(Checker* d_checker, CheckerNode* &list_head) // pass by address
{
if(list_head== NULL) // throw exception
else
{
    CheckerNode*temp = NULL, *previous = NULL;
    Checker* c_checker= new Checker; 
    temp = list_head;
    while(temp != NULL && temp->node!= NULL)
    {
        c_checker= temp->node;
        if(d_checker!= c_checker) 
        {
            previous = temp;
            temp = temp->next;
        }
        else
        {
            if(temp != list_head)
            {
                previous->next = temp->next;
                delete temp;
                temp = NULL;
            }
            else if(temp == list_head) // this is where head should get deleted
            {    
                temp = list_head;
                list_head= list_head->next;
                delete temp;
                temp = NULL;
            }

                     delete c_checker; 
                     c_checker = nullptr;

            return;
        }
    }
}
}