我对C ++和它的数据结构都很陌生。我为我的Doubly Linked List Class做了一些功能,但我特别在删除功能方面遇到了麻烦。我已经创建了一个deleteHead()函数,它删除了列表中的第一个节点,一个deleteTail()函数删除了列表中的最后一个节点,最后删除了一个deleteElement(Item)函数。并删除其中包含该项的节点。
问题是,每当我尝试从列表中删除唯一剩余的节点时,程序就会崩溃。即如果我插入一个节点然后在同一节点上调用deleteElement函数(如果我插入的节点是列表中唯一的节点),程序就会崩溃。
这是我的代码。
template <class T>
void LinkedList<T>::deleteElement(T item)
{
ListItem<T>* current = head;
ListItem<T>* temp;
if (head == NULL) { // if list is empty end the function
return;
}
while (current) {
if (current->value == item) {
if (current == head) { // if item is in the head
deleteHead();
}
else if (current == getTail()) { // if item is in the tail
deleteTail();
}
// if item is between two nodes
else if (current != head && current != getTail()) {
temp = current;
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
current->next = NULL;
current->prev = NULL;
if (current->next == NULL) {
deleteTail();
}
}
}
current = current->next;
}
}
// Delete the Head Node
template <class T>
void LinkedList<T>::deleteHead()
{
if (head != NULL) { // as long as head is not null, delete head
ListItem<T> *current = head;
head = head->next;
current->next = NULL;
head->prev = NULL;
} else {return;} // if head is null, end the function without doing anything
}
// Delete Tail Node
template <class T>
void LinkedList<T>::deleteTail()
{
ListItem<T> *tail = getTail();
tail = tail->prev;
tail->next->prev = NULL;
tail->next = NULL;
}
答案 0 :(得分:0)
您的代码中存在多个问题。首先,在访问它们之前,您没有检查任何指针。例如,这里:
temp = current;
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
如果列表中只有一个元素,则其next
和prev
成员可能为空。这意味着尝试将内容分配给temp->prev->next
或temp->next->prev
将违反访问权限。
同样适用于其他地方,包括while
循环结束时的这一行:
current = current->next;
在该阶段,current
可能会被假设删除,这意味着尝试访问其next
成员会失败。由于另一个问题,它现在可能不会失败......
非常重要的是,你实际上并没有删除任何东西。 C ++没有垃圾收集器,所以你不能只是将原始指针设置为null而忘记它。您必须在其上调用delete
来销毁和取消分配对象,否则会导致内存泄漏。您需要在整个代码中修复它,然后可能修改所有功能。在删除对象后,您需要非常小心不要访问对象。
话虽如此,你应该使用智能指针(即std::shared_ptr
),而不是使用原始指针。当没有其他指针指向它时,它们会为您删除对象。您仍然需要避免访问已删除的对象,但它使编码更简单,并且希望更现代/更健壮。
答案 1 :(得分:0)
第1步 - 将成员变量ListItem<T>* tail
添加到课程ListItem<T>
。
第2步 - 将所有对getTail()
的来电替换为tail
。
第3步 - 在功能deleteElement
中,您可以替换:
else if (current != head && current != tail)
使用:
else
第4步 - 在功能deleteElement
中,您应替换:
current->next = NULL;
current->prev = NULL;
if (current->next == NULL)
deleteTail();
使用:
delete current;
第5步 - 重写函数deleteHead
,如下所示:
ListItem<T>* current = head;
if (head == tail)
head = tail = NULL;
else
head = head->next;
delete current;
第6步 - 重写函数deleteTail
,如下所示:
ListItem<T>* current = tail;
if (tail == head)
tail = head = NULL;
else
tail = tail->prev;
delete current;
答案 2 :(得分:0)
得到了正确答案。这是我的数据结构分配中的一个问题。这是我实现的代码。是的,我知道它有冗余和低效率,但我必须在任务框架内工作。
这是我的deleteElement()函数:
template <class T>
void LinkedList<T>::deleteElement(T item)
{
ListItem<T>* current = head;
ListItem<T>* temp;
if (head == NULL) { // if list is empty end the function
return;
}
while (current) {
if (current->value == item) {
if (current == head) { // if item is in the head
deleteHead();
}
else if (current == getTail()) { // if item is in the tail
deleteTail();
}
else if (current != head && current != getTail()) {
// if item is between two nodes
temp = current;
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
current->next = NULL;
current->prev = NULL;
if (current->next == NULL) {
deleteTail();
}
}
}
current = current->next;
}
}