C ++删除双向链表中的元素函数

时间:2014-02-07 08:16:10

标签: c++ doubly-linked-list

我对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;
}

3 个答案:

答案 0 :(得分:0)

您的代码中存在多个问题。首先,在访问它们之前,您没有检查任何指针。例如,这里:

temp = current;
temp->prev->next = temp->next;
temp->next->prev = temp->prev;

如果列表中只有一个元素,则其nextprev成员可能为空。这意味着尝试将内容分配给temp->prev->nexttemp->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;
    }
}