在链表中没有添加虚拟头结点的情况下,删除链表第一个节点程序报错。

来源:5-3 设立链表的虚拟头结点 Remove Linked List Elements

沙皮狗yy

2017-07-22

#include <iostream>

using namespace std;

///Definition for singly-linked list.
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

/// LinkedList Test Helper Functions
ListNode* createLinkedList(int arr[], int n){

    if( n == 0 )
        return NULL;

    ListNode* head = new ListNode(arr[0]);
    ListNode* curNode = head;
    for( int i = 1 ; i < n ; i ++ ){
        curNode->next = new ListNode(arr[i]);
        curNode = curNode->next;
    }

    return head;
}

void printLinkedList(ListNode* head){

    if( head == NULL ){
        cout<<"NULL"<<endl;
        return;
    }

    ListNode* curNode = head;
    while( curNode != NULL ){
        cout<<curNode->val;
        if( curNode->next != NULL )
            cout<<" -> ";
        curNode = curNode->next;
    }

    cout<<endl;

    return;
}

void deleteLinkedList(ListNode* head){

    ListNode* curNode = head;
    while( curNode != NULL ){
        ListNode* delNode = curNode;
        curNode = curNode->next;
        delete delNode;
    }

    return;
}

// 不使用虚拟头结点
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {

        //在循环过程中不断的访问head—>val,
        //要保证每次进入循环时head都不为空!
        while( head != NULL && head->val == val ){

            ListNode* node = head;
            head = head->next;
            delete node;
        }
        //执行完上面的操作之后,就会由一个新的head
        //此时也要保证head不为NULL
        if( head == NULL )
            return head;

        ListNode* cur = head;
        while( cur->next != NULL ){

            if( cur->next->val == val ){
                ListNode* delNode = cur->next;
                cur->next = delNode->next;
                delete delNode;
            }
            else
                cur = cur->next;
        }

        return head;
    }
};

int main() {

    int arr[] = {1, 2, 6, 3, 4, 5, 6};
    int n = sizeof(arr)/sizeof(int);

    ListNode* head = createLinkedList(arr, n);
    printLinkedList(head);

    Solution().removeElements( head, 1);
    printLinkedList(head);

    deleteLinkedList( head );

    return 0;
}

老师您好,上面是完整的代码,我删除第一个节点时,按照您的代码,程序会报错。

下面是我用gdb调试的结果,看调试的结果是 在deleteLinkedList()这个函数中调用delete delNode;这个语句时报错!

而且删除了头结点之后打印的结果是0 -> 2 -> 6 -> 3 -> 4 -> 5 -> 6,从调试结果看只是把头结点的val给置0了,并没有真正delete掉这个节点。

Breakpoint 1, main () at main.cpp:93
93    int arr[] = {1, 2, 6, 3, 4, 5, 6};
(gdb) n
94    int n = sizeof(arr)/sizeof(int);
(gdb) n
96    ListNode* head = createLinkedList(arr, n);
(gdb) n
97    printLinkedList(head);
(gdb) n
1 -> 2 -> 6 -> 3 -> 4 -> 5 -> 6
99    Solution().removeElements( head, 1);
(gdb) n
100    printLinkedList(head);
(gdb) n
0 -> 2 -> 6 -> 3 -> 4 -> 5 -> 6
102    deleteLinkedList( head );
(gdb) s
deleteLinkedList (head=0x603010) at main.cpp:50
50    ListNode* curNode = head;
(gdb) n
51    while( curNode != NULL ){
(gdb) n
52        ListNode* delNode = curNode;
(gdb) n
53        curNode = curNode->next;
(gdb) n
54        delete delNode;
(gdb) n
*** Error in `/root/yuyang/program/liuyubo2/05-About-Linked-List/Course Code (C++)/03-Remove-Linked-List-Elements/a.out': double free or corruption (fasttop): 0x0000000000603010 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x7c503)[0x7ffff7277503]
/root/yuyang/program/liuyubo2/05-About-Linked-List/Course Code (C++)/03-Remove-Linked-List-Elements/a.out[0x400abe]
/root/yuyang/program/liuyubo2/05-About-Linked-List/Course Code (C++)/03-Remove-Linked-List-Elements/a.out[0x400b5a]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7ffff721cb35]
/root/yuyang/program/liuyubo2/05-About-Linked-List/Course Code (C++)/03-Remove-Linked-List-Elements/a.out[0x400889]
======= Memory map: ========
00400000-00401000 r-xp 00000000 ca:01 1983859                            /root/yuyang/program/liuyubo2/05-About-Linked-List/Course Code (C++)/03-Remove-Linked-List-Elements/a.out
00601000-00602000 r--p 00001000 ca:01 1983859                            /root/yuyang/program/liuyubo2/05-About-Linked-List/Course Code (C++)/03-Remove-Linked-List-Elements/a.out
00602000-00603000 rw-p 00002000 ca:01 1983859                            /root/yuyang/program/liuyubo2/05-About-Linked-List/Course Code (C++)/03-Remove-Linked-List-Elements/a.out
00603000-00624000 rw-p 00000000 00:00 0                                  [heap]
7ffff0000000-7ffff0021000 rw-p 00000000 00:00 0 
7ffff0021000-7ffff4000000 ---p 00000000 00:00 0 
7ffff71fb000-7ffff73b2000 r-xp 00000000 ca:01 1507907                    /usr/lib64/libc-2.17.so
7ffff73b2000-7ffff75b1000 ---p 001b7000 ca:01 1507907                    /usr/lib64/libc-2.17.so
7ffff75b1000-7ffff75b5000 r--p 001b6000 ca:01 1507907                    /usr/lib64/libc-2.17.so
7ffff75b5000-7ffff75b7000 rw-p 001ba000 ca:01 1507907                    /usr/lib64/libc-2.17.so
7ffff75b7000-7ffff75bc000 rw-p 00000000 00:00 0 
7ffff75bc000-7ffff75d1000 r-xp 00000000 ca:01 1510624                    /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7ffff75d1000-7ffff77d0000 ---p 00015000 ca:01 1510624                    /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7ffff77d0000-7ffff77d1000 r--p 00014000 ca:01 1510624                    /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7ffff77d1000-7ffff77d2000 rw-p 00015000 ca:01 1510624                    /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7ffff77d2000-7ffff78d2000 r-xp 00000000 ca:01 1510688                    /usr/lib64/libm-2.17.so
7ffff78d2000-7ffff7ad2000 ---p 00100000 ca:01 1510688                    /usr/lib64/libm-2.17.so
7ffff7ad2000-7ffff7ad3000 r--p 00100000 ca:01 1510688                    /usr/lib64/libm-2.17.so
7ffff7ad3000-7ffff7ad4000 rw-p 00101000 ca:01 1510688                    /usr/lib64/libm-2.17.so
7ffff7ad4000-7ffff7bbd000 r-xp 00000000 ca:01 1507953                    /usr/lib64/libstdc++.so.6.0.19
7ffff7bbd000-7ffff7dbd000 ---p 000e9000 ca:01 1507953                    /usr/lib64/libstdc++.so.6.0.19
7ffff7dbd000-7ffff7dc6000 r--p 000e9000 ca:01 1507953                    /usr/lib64/libstdc++.so.6.0.19
7ffff7dc6000-7ffff7dc8000 rw-p 000f2000 ca:01 1507953                    /usr/lib64/libstdc++.so.6.0.19
7ffff7dc8000-7ffff7ddd000 rw-p 00000000 00:00 0 
7ffff7ddd000-7ffff7dfd000 r-xp 00000000 ca:01 1507900                    /usr/lib64/ld-2.17.so
7ffff7fed000-7ffff7ff2000 rw-p 00000000 00:00 0 
7ffff7ff7000-7ffff7ffa000 rw-p 00000000 00:00 0 
7ffff7ffa000-7ffff7ffc000 r-xp 00000000 00:00 0                          [vdso]
7ffff7ffc000-7ffff7ffd000 r--p 0001f000 ca:01 1507900                    /usr/lib64/ld-2.17.so
7ffff7ffd000-7ffff7ffe000 rw-p 00020000 ca:01 1507900                    /usr/lib64/ld-2.17.so
7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Program received signal SIGABRT, Aborted.
0x00007ffff72301d7 in raise () from /lib64/libc.so.6

看了很久的代码,不知道问题出在哪里,麻烦老师能解答一下

写回答

1回答

liuyubobobo

2017-07-22

我没有运行你的代码,但是直观看下来有一个问题。当你在main函数运行这句话以后:

Solution().removeElements( head, 1);


你的main函数中的head指针已经被delete掉了,此时你后续的这些代码:

printLinkedList(head);
deleteLinkedList( head );


访问这个head是危险的。当删除的是链表的头结点的时候,要把新的头结点返回赋值回来。改成这样:

head = Solution().removeElements( head, 1);


再试试看?加油!


1
2
慕莱坞1557513
我也是这个问题,自己发现了这个问题改了。
2021-11-01
共2条回复

玩转算法面试-- Leetcode真题分门别类讲解

课程配套大量BAT面试真题,高频算法题解析,强化训练

7408 学习 · 1150 问题

查看课程