删除链接列表中的前端元素

时间:2013-10-11 20:25:03

标签: c++ linked-list

我正在尝试编写一个删除链表前面元素的函数,并将头指针设置为删除后的下一个元素。

这是我的代码:

void LinkedList::delete_front(){
    if(head != NULL){
            if(head->next != NULL){
                    ListNode *tmp = head;
                    delete head;
                    head = tmp->next;
            }
            else {delete head; head = NULL;}
    }
    size--;
}

这是我的班级定义:

class ListNode{

    public:
            Item data;
            ListNode *next;
};
class LinkedList{

    private:
            ListNode *head;
            int size;

    public:
            LinkedList();
            ~LinkedList(); 
            bool empty();
            void insert_front(Item i);
            void insert_back(Item i);
            void delete_front();
            void delete_back();
            void print();
};

Annddddd .....这是问题,当在valgrind中运行时,在第一次delete_front()调用之前会弹出这个错误:

==4738== Invalid read of size 8
==4738==    at 0x400B3C: LinkedList::delete_front() (in /home/jon/jball2_lab06/linkedlist)
==4738==    by 0x400E59: main (in /home/jon/jball2_lab06/linkedlist)
==4738==  Address 0x5a03f98 is 8 bytes inside a block of size 16 free'd
==4738==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4738==    by 0x400B37: LinkedList::delete_front() (in /home/jon/jball2_lab06/linkedlist)
==4738==    by 0x400E59: main (in /home/jon/jball2_lab06/linkedlist)

4 个答案:

答案 0 :(得分:3)

您正在删除元素,之后,您尝试访问它。这些是:

ListNode *tmp = head;
delete head;
head = tmp->next; // tmp was initialized to head, but head was just deleted!

应该是:

ListNode *tmp = head->next;
delete head;
head = tmp;

更新:我刚刚意识到,通过上述方法,整个方法可以变得更加容易:

void LinkedList::delete_front()
{
    if(head != NULL) {
        ListNode *tmp = head->next;
        delete head;
        head = tmp;
        --size;
    }
}

适用于所有情况。您不必检查head->next == NULL,因为上面也会处理它。它还修复了代码中的错误,即使列表为空,我在size块内移动--size,也会减少if(head != NULL)。{/ p>

请注意,这会保留原始语义,即“如果列表为空,则不执行任何操作”。这通常不是你想要的,考虑抛出异常:

void LinkedList::delete_front()
{
    if(head == NULL) {
        throw std::runtime_exception( "LinkedList::delete_front() "
                                      "called with empty list" );
    }

    ListNode *tmp = head->next;
    delete head;
    head = tmp;
    --size;
}

答案 1 :(得分:3)

问题在这里:

if(head->next != NULL){
    ListNode *tmp = head;
    delete head;
    head = tmp->next;
}

您将temp指定给head,然后删除head。然后尝试再次访问它。

答案 2 :(得分:1)

你的问题就在这里:

                ListNode *tmp = head;
                delete head;
                head = tmp->next;

你将tmp设置为head,然后删除head,然后使用tmp。 tmp指向刚刚删除的内存。

相反,将tmp设置为head,将head设置为head-> next,然后删除tmp。

答案 3 :(得分:1)

如果您使用智能指针,它将缩减为:

void LinkedList::delete_front() {
    if(head != NULL) {
        head = head->next;
        --size;
    }
}

其中:

class ListNode{
    public:
        Item data;
        unique_ptr<ListNode> next;
};

class LinkedList{
    private:
        unique_ptr<ListNode> head;
//.. etc

此外,即使headNULL,我也已修复了尺寸减小的错误。