我会坦率地为请求您的帮助而道歉。我真的不配得到它。我也为我所知道的草率的代码道歉。我不想成为那个的人,但我真的很困惑我该怎么做。
到目前为止的情况如下:
列表.cpp
Node::Node()
{
next = nullptr;
book = nullptr;
}
Node::Node(Book* newBook)
{
next = nullptr;
book = newBook;
}
Node::~Node()
{
if (next != nullptr)
{
delete book;
}
}
Node* Node::getNextNode() const
{
return next;
}
void Node::setNext(Node* newNext)
{
if (newNext == nullptr)
{
next = nullptr;
}
else
{
next = newNext;
}
}
Book* Node::getBook() const
{
return book;
}
List::List()
{
first = nullptr;
last = nullptr;
numNodes = 0;
}
List::~List()
{
Node* tempNode = first;
first = first->getNextNode();
while (first != nullptr)
{
delete tempNode;
numNodes--;
tempNode = first;
first = first->getNextNode();
}
last = nullptr;
}
void List::push_front(Node* newNode)
{
Node* tempNode = first;
newNode->setNext(tempNode);
first = newNode;
if (last == nullptr)
{
last = first;
}
numNodes++;
}
void List::push_back(Node* newNode)
{
Node* tempNode = last;
tempNode->setNext(newNode);
last = newNode;
if (first == nullptr)
{
first = last;
}
numNodes++;
}
Node* List::pop_front()
{
if (first != nullptr)
{
Node* tempNode = first;
if (tempNode->getNextNode() == nullptr)
{
numNodes--;
return first;
}
if (first == last)
{
numNodes--;
first = nullptr;
return first;
}
first = first->getNextNode();
numNodes--;
return tempNode;
}
return nullptr;
}
Node* List::pop_back()
{
if (last != nullptr)
{
Node* tempNode = first;
if (first == last)
{
numNodes--;
first = nullptr;
return first;
}
if (tempNode->getNextNode() == nullptr)
{
numNodes--;
return first;
}
while (tempNode->getNextNode()->getNextNode() != nullptr)
{
tempNode = tempNode->getNextNode();
}
last = tempNode;
last->next = nullptr;
numNodes--;
return tempNode;
}
return nullptr;
}
Node* List::getFirst() const
{
return first;
}
Node* List::getLast() const
{
return last;
}
驱动程序.cpp
int main()
{
// set up cout for displaying prices
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
// create a List object
List partsList;
cout << "nPart I: multiple node test: push_front and pop_frontn";
cout << "n----------------------------------n";
// build a List using push_front
partsList.push_front(new Node(new Book("Fun With C++", "I. M. Codemann", 95.00)));
partsList.push_front(new Node(new Book("Lousy Linked Lists", "B. A. Hacker", 74.90)));
partsList.push_front(new Node(new Book("Programming Nuts", "R. U. Krazy", 85.25)));
partsList.push_front(new Node(new Book("Silly Syntax", "Irma Coder", 30.15)));
cout << "nThe original nodes in the List:n";
printList(partsList);
cout << "n----------------------------------n";
// test push_front function
cout << "nAdding to the front of the List:n";
cout << "n----------------------------------n";
partsList.push_front(new Node(new Book("Python's a Snake", "C. Rules", 65.45)));
partsList.push_front(new Node(new Book("Programming Fables", "J. Aesop", 73.15)));
printList(partsList);
cout << "n----------------------------------n";
// test pop-front
cout << "nRemoving the first node from the list.n";
cout << "n----------------------------------n";
Node* item = partsList.pop_front();
printList(partsList);
if (item != NULL)
delete item;
cout << "n----------------------------------n";
cout << "nPart Two: Push_back and pop_back";
// test push_back
partsList.push_back(new Node(new Book("Coding Shortcuts", "B. Lazy", 110.25)));
partsList.push_back(new Node(new Book("Famous Programmers I Know", "M. T. Set", 126.00)));
cout << "nAdding two nodes at the endn";
cout << "n----------------------------------n";
printList(partsList);
// test pop-back
cout << "n----------------------------------n";
cout << "nRemove last node from the listn";
cout << "n----------------------------------n";
item = partsList.pop_back();
printList(partsList);
if (item != NULL)
delete item;
// delete all of the Nodes in the list
cout << "nEmpty the list and delete all nodesn";
while (partsList.getFirst() != nullptr)
{
Node * t = partsList.pop_front();
delete t;
}
printList(partsList);
// Test Push_front and pop_back - do they handle special case
cout << "nTesting special case handling for push_front and pop_backn";
partsList.push_front(new Node(new Book("Test Book 1", "nobody", 1.25)));
Node* t = partsList.pop_back();
cout << "nThe Node just removed contains " << t->getBook()->getTitle() << endl;
delete t;
// Test push_back and pop_front - do they handle special cases
cout << "nTesting special case handling for push_back and pop_frontn";
partsList.push_back(new Node(new Book("Test Book 2", "nobody", 1.25)));
t = partsList.pop_front();
cout << "nThe Node just removed contains " << t->getBook()->getTitle() << endl;
delete t;
// Is the list now empty
cout << "nThe list should now be empty...n";
printList(partsList);
cout << "n-------------------------------------------n";
cout << "nEnd of Test";
cout << "n-------------------------------------------n";
system("PAUSE");
return 0;
}
void printList(const List& theList)
{
if (theList.getFirst() == nullptr) // if the list is empty
cout << "nempty listn";
else
{
Node* t = theList.getFirst();
while (t != NULL)
{
Book* bp = t->getBook();
cout << bp->getTitle() << ' ';
cout << bp->getAuthor() << ' ';
cout << "$" << bp->getPrice() << endl;
t = t->getNextNode();
}
}
}
void printFirstNode(List theList)
{
Node* t = theList.getFirst();
Book* bp = t->getBook();
cout << bp->getTitle() << ' ';
cout << bp->getAuthor() << ' ';
cout << "$" << bp->getPrice() << endl;
t = t->getNextNode();
}
好吧,到目前为止,我的链接列表似乎运行得相对顺利。该程序仅在最后一次printList函数调用的hometretch处引发异常(Proj_02.exe中0x00E5654B处的未处理异常:0xC0000005:读取位置0xDDDDDF1的访问冲突。)。我真的不知道为什么会抛出这个异常,列表应该是完全空的。所以,我必须羞愧地垂下头。我应该怎么做才能解决这个问题?
谢谢。发自内心。
托马兹的回答到目前为止是正确的,只是一些额外的提示:
无论您在哪里将first或last中的一个设置为nullptr,也可以为另一个设置:
first = last = nullptr;
push_back
不起作用,如果列表是空的,那么最后一个是nullptr本身。试试这个:
if(!last)
{
first = last = newNode;
}
else
{
last->setNext(newNode);
last = newNode;
}
++numNodes;
Node类应该是列表类的内部细节,否则您可以在列表不知情的情况下从外部修改列表!将Node设为内部类,并更改List的公共接口,使其在以前有Node*的地方处理Book*。然后在列表的函数中创建和删除节点,不要从节点的析构函数中删除Book。不过,您仍然可以使用Node类来迭代List,因此它将对应于:std::List的迭代器。
你可以直接分配newNext:即使它是一个空指针,next
仍然会被分配这个,所以检查是多余的:
void Node::setNext(Node* newNext)
{
// if (newNext == nullptr)
//{
// next = nullptr;
//}
//else
//{
next = newNext;
//}
}
我可以假设你写这份清单是为了学习吗?否则,您可能会使用STL中的::std::list。。。
我允许自己重写你的列表类,这样你就可以比较了。希望这能帮助你。。。
class List
{
public:
List();
~List();
class Node
{
public:
Node const* getNext() const
{
return next;
}
Book* getBook() const
{
return book;
}
private:
friend class List;
Node(Book*);
Node* next;
Book* book;
};
void push_front(Book* book);
void push_back(Book* book);
Book* pop_front();
Book* pop_back();
Book* getFirst() const;
Book* getLast() const;
Node const* getFirstNode() const
{
return first;
}
private:
Node* first;
Node* last;
unsigned int numNodes;
};
List::Node::Node(Book* newBook)
: next(nullptr), book(newBook)
{
}
List::List()
: first(nullptr), last(nullptr), numNodes(0)
{
}
List::~List()
{
while (first)
{
Node* tempNode = first;
first = first->next;
delete tempNode;
}
}
void List::push_front(Book* book)
{
Node* node = new Node(book);
if (first)
{
node->next = first;
first = node;
}
else
{
first = last = node;
}
++numNodes;
}
void List::push_back(Book* book)
{
Node* node = new Node(book);
if (last)
{
last->next = node;
last = node;
}
else
{
first = last = node;
}
++numNodes;
}
Book* List::pop_front()
{
Book* book = nullptr;
if (first)
{
book = first->book;
Node* tempNode = first;
first = first->next;
if (!first)
{
last = nullptr;
}
delete tempNode;
--numNodes;
}
return book;
}
Book* List::pop_back()
{
Book* book = nullptr;
if (last)
{
book = last->book;
Node* tempNode = first;
if (first == last)
{
first = last = nullptr;
}
else
{
while(tempNode->next != last)
{
tempNode = tempNode->next;
}
delete last;
last = tempNode;
last->next = 0;
}
--numNodes;
}
return book;
}
Book* List::getFirst() const
{
return first ? first->book : nullptr;
}
Book* List::getLast() const
{
return last ? last->book : nullptr;
}
您的崩溃似乎与以下代码部分有关:
Node* List::pop_front()
{
if (first != nullptr)
{
Node* tempNode = first;
if (tempNode->getNextNode() == nullptr)
{
numNodes--;
return first;
}
if (first == last)
{
numNodes--;
first = nullptr;
return first;
}
first = first->getNextNode();
numNodes--;
return tempNode;
}
return nullptr;
}
两种情况:
if (tempNode->getNextNode() == nullptr)
{
numNodes--;
return first;
}
if (first == last)
{
numNodes--;
first = nullptr;
return first;
}
似乎服务于单个元素列表(first == last
和next == nullptr
)的目的。所以,第一个应该是:
if (tempNode->getNextNode() == nullptr)
{
numNodes--;
first = nullptr;
return tempNode;
}
此外:
Node::Node(Book* newBook)
{
next = nullptr;
book = newBook;
}
Node::~Node()
{
if (next != nullptr)
{
delete book;
}
}
在调用的情况下是100%泄漏,如:
new Node(new Book("Test Book 1", "nobody", 1.25))
由于next
仍然是nullptr
,并且book
应该由Node
拥有,但不是。此外,最后一个滤芯总是会泄漏。