2

我现在正在练习链表结构,并且我已经使用该算法编写了一个程序。在程序中有一个递归方法来删除链表的每个元素。但是,该程序在该方法中崩溃。

void exit()
{
    Person* person = phead;
    exterminateStartingFrom(person);
}

void exterminateStartingFrom(Person* person)
{
    Person* nextperson;
    nextperson = person->getNext();
    if(nextperson){
        exterminateStartingFrom(nextperson);
    }
    delete person;
}

此方法在用户想要退出时运行。“phead”代表人员列表的第一个元素。显示的问题是:双重释放或损坏(fasttop)

这是类 Person :

class Person {
private:
    std::string firstname;
    std::string lastname;
    int age;
    Person* next;

public:
    Person(std::string, std::string, int);
    void printDescription();
    void printFirstname();
    void printLastname();
    void printAge();
    void setNext(Person*);
    Person* getNext();


};

谢谢。

4

3 回答 3

1

以下是我采取的方法。当然,这有点做作,因为我不知道您的实际功能。我还用初始全局变量表示 pHead,并使用具有超出范围值的年龄来指示列表的头部。

对于列表的头部,我使用了一个特殊的构造函数。

有更好的方法可以做到这一点,但是在这个快速而肮脏的实现中,我需要一些东西来表明在递归期间退出时,我知道什么时候我已经一直支持到列表的头部。

#include <string>

class Person {
private:
    std::string firstname;
    std::string lastname;
    int age;
    Person* next;

public:
    Person (void);                           // constructor for the pHead
    ~Person (void);
    Person(std::string, std::string, int);   // standard constructor used
    std::string getFirstname(void) { return firstname; };
    std::string getLastname(void) { return lastname; }
    void setNext(Person *newNext) { next = newNext; }
    Person* getNext() { return next; }
    Person *addToListAt (Person *personList);
    void addToListAtEnd (Person *personList);
    void Person::insertListAfter (Person *personList);
    bool isHeadOfList (void);
};

Person pHead = Person();

// special constructor used to create the head to a linked list
Person::Person ()
{
    age = -1;
    next = 0;
}

// standard constructor used to create a list item.
Person::Person (std::string sFirstName, std::string sLastName, int myAge)
{
    if (myAge < 0) myAge = 0;
    firstname = sFirstName;
    lastname = sLastName;
    age = myAge;
    next = 0;
}

Person::~Person ()
{
    next = 0;
    age = 0;
}

void exterminateStartingFrom(Person* person)
{
    Person* nextPerson;
    nextPerson = person->getNext();
    if(nextPerson){
        exterminateStartingFrom(nextPerson);
    }

    if (! person->isHeadOfList())
        delete person;
}

Person *Person::addToListAt (Person *personList)
{
    Person* nextPerson;
    nextPerson = personList->getNext();
    personList->setNext (this);
    return nextPerson;
}

void Person::insertListAfter (Person *personList)
{
    Person* nextPerson;
    nextPerson = personList->getNext();
    personList->setNext (this);
    next = nextPerson;
}

void Person::addToListAtEnd (Person *personList)
{
    Person* nextperson;
    nextperson = personList->getNext();
    if(nextperson){
        addToListAtEnd (nextperson);
    } else {
        personList->setNext (this);
    }
}

bool Person::isHeadOfList (void)
{
    // we use a special age to represent the head of the list
    // the head does not contain any data except for point to first item
    // in the list.
    return (age < 0);
}

int main(int argc, char * argv[])
{
    Person *newPerson = new Person("first_1", "last_1", 11);
    newPerson->addToListAtEnd (&pHead);
    newPerson = new Person("first_2", "last_2", 22);
    newPerson->addToListAtEnd (&pHead);
    newPerson = new Person("first_3", "last_3", 33);
    newPerson->addToListAtEnd (&pHead);

    Person *itemPerson = pHead.getNext();
    newPerson = new Person("first_11", "last_11", 12);

    newPerson->insertListAfter (itemPerson);

    exterminateStartingFrom(&pHead);
    return 0;
}
于 2012-09-02T16:16:30.710 回答
1

您的列表是单向链接还是双向链接?如果您有一个双向列表(您不仅存储指向下一个元素的指针,还存储指向前一个元素的指针)并且调用析构函数,则可能还删除由previousnext字段指示的元素。当递归返回一个级别并且您想要删除倒数第二个元素时,您会收到错误。

于 2012-09-02T14:33:13.557 回答
1

如果不知道如何构建或删除 Person 对象,很难说清楚。您的错误消息意味着您要删除同一实体两次,或者您要删除未分配的内容。可以尝试打印您要删除的地址,以便检查是否有相同的地址被多次删除?

还要处理传递给递归方法的指针是nill.

于 2012-09-02T14:40:05.313 回答