我有以下两个功能,它们根本不会改变我的链接列表。我考虑到如果给定节点为空,我然后检查给定节点是头还是尾,然后我插入需要的地方并更正节点指向的位置。我必须错过一小部分,但我不确定是什么。有任何想法吗?谢谢!
// insert the new object after the node p
void DoublyLinkedList::insertAfter(DListNode &p, int newobj) {
if(isEmpty()) {
throw EmptyDLinkedListException("Empty Doubly Linked List");
}
DListNode *newNode = new DListNode();
newNode->obj = newobj;
newNode->prev = &p;
newNode->next = p.next;
if (p.next != NULL) {
p.next->prev = newNode;
}
p.next = newNode;
if(&trailer == &p){
trailer = *newNode;
}
}
// insert the new object before the node p
void DoublyLinkedList::insertBefore(DListNode &p, int newobj){
if(isEmpty()) {
throw EmptyDLinkedListException("Empty Doubly Linked List");
}
DListNode *newNode = new DListNode();
newNode->obj = newobj;
newNode->prev = p.prev;
newNode->next = &p;
if(&header == &p){
header = *newNode;
}
if (p.prev != NULL) {
p.prev->next = newNode;
}
}
我有一个最初的列表:
100 90 80 70 60 50 40 30 20 10 10 20 30 40 50 60 70 80 90 100
然后我实现insertAfter函数在80后插入15:
cout << "On list2 insert 15 after 80. " << endl;
DListNode location = *dll2.getFirst()->next->next;
dll2.insertAfter(location, 15);
cout << "list2: " << dll2 << endl << endl;
根据调试器,一切都指向正确的位置,但上面函数调用的结果是:
On list2 insert 15 after 80.
list2: 100 90 80 70 60 50 40 30 20 10 10 20 30 40 50 60 70 80 90 100
奇怪的是,当我实现insertAfter然后insertBefore之类的时候:
// add tests for insertAfter
cout << "On list2 insert 15 after 80. " << endl;
DListNode location = *dll2.getFirst()->next->next;
dll2.insertAfter(location, 15);
cout << "list2: " << dll2 << endl << endl;
//insertBefore
cout << "On list2 insert 9 before 80. " << endl;
dll2.insertBefore(location, 9);
cout << "list2: " << dll2 << endl << endl;
输出是这样的:
On list2 insert 15 after 80.
list2: 100 90 80 70 60 50 40 30 20 10 10 20 30 40 50 60 70 80 90 100
On list2 insert 9 before 80.
list2: 100 90 9 80 15 70 60 50 40 30 20 10 10 20 30 40 50 60 70 80 90 100
显示之前插入了9,之后插入了15,但是当函数结束时,析构函数中存在一个段错误,表示正在删除的节点未被分配。
答案 0 :(得分:0)
链表是指针列表。您的列表的header
和trailer
字段需要是DListNode*
个指针,而不是DListNode
个对象实例。如果它们不是指针,它们就无法列出管理。
您的代码未正确更新p
节点周围的节点。即使您必须更新header
或trailer
字段,您仍然必须更新其他节点。但你不是那样做的。
通过引用传递节点也不习惯,但无论如何你都是这样做的。我之前并不想对此说些什么,但你真的应该用指针传递它们。
您的代码看起来应该更像这样:
private:
DListNode *header, *trailer;
...
void DoublyLinkedList::insertAfter(DListNode *p, int newobj)
{
DListNode *newNode = new DListNode();
newNode->obj = newobj;
newNode->prev = p;
newNode->next = p->next;
if (p->next != NULL) {
p->next->prev = newNode;
}
p->next = newNode;
if (trailer == p) {
trailer = newNode;
}
}
void DoublyLinkedList::insertBefore(DListNode *p, int newobj)
{
DListNode *newNode = new DListNode();
newNode->obj = newobj;
newNode->prev = p->prev;
newNode->next = p;
if (p->prev != NULL) {
p->prev->next = newNode;
}
if (header == p) {
header = newNode;
}
}
话虽如此,正如我在之前的问题中建议的那样,一旦你理解双链表如何工作,你应该丢弃所有这些代码,而只是使用STL std::list
类,这是一个标准的双链表实现。