尝试在给定节点之前删除

时间:2017-07-31 19:09:38

标签: c++ linked-list

我有以下两个函数,我可以让removeAfter函数正常工作,但是当试图实现removeBefore函数时,链接列表根本没有改变。我错过了什么吗?我已经做了必要的更改,但仍然得到相同的结果:removeBefore不会输出任何更改列表。

    // remove the node after the node p
void DoublyLinkedList::removeAfter(DListNode &p){
    if (isEmpty()){
        throw EmptyDLinkedListException("Empty Doubly Linked List");
    }

    DListNode *to_delete = &p;
    to_delete = to_delete->next;

    if (to_delete != NULL){
        if(to_delete->next != NULL){
            to_delete->prev->next = to_delete->next;
        }

        if(to_delete->prev != NULL){
            to_delete->next->prev = &p;
        }
        if (to_delete == &trailer) {
            trailer = *to_delete->prev;
        }


    }
    if (to_delete == NULL){
        throw EmptyDLinkedListException("Cannot delete a null pointer");
    }
    delete to_delete;
}

// remove the node before the node p
void DoublyLinkedList::removeBefore(DListNode &p){
        /* Complete this function */
    if (isEmpty()){
        throw EmptyDLinkedListException("Empty Doubly Linked List");
    }

    DListNode *to_delete = &p;
    to_delete = to_delete->prev;

    if (to_delete != NULL){
        if (to_delete->next != NULL) {
            to_delete->next->prev = to_delete->prev;
        }
        if (to_delete->prev != NULL) {
            to_delete->prev->next = to_delete->next;
        }

        if (to_delete == &header) {
             header = *to_delete->next;
        }

    }

    if (to_delete == NULL){
        throw EmptyDLinkedListException("Cannot delete a null pointer");
    }

    delete to_delete;
}

1 个答案:

答案 0 :(得分:1)

您的代码中存在错误。

首先,链表是一个指针列表,因此不习惯通过引用传递节点。你真的应该用指针传递它们。

removeAfter()没有考虑输入时p.next可能为NULL的可能性(当p是列表中的最后一个节点时)。并且在删除to_delete之前,它不会正确更新to_delete的兄弟姐妹。它看起来应该是这样的:

void DoublyLinkedList::removeAfter(DListNode *p)
{
    DListNode *to_delete = p->next; //Get to the node after p that is to be deleted
    if (to_delete != NULL)
    {
        if (to_delete->next != NULL) {
            to_delete->next->prev = to_delete->prev;
        }

        if (to_delete->prev != NULL) {
            to_delete->prev->next = to_delete->next;
        }


        // update the tail pointer if to_delete is the tail node...
        if (trailer == to_delete) {
            trailer = to_delete->prev;
        }

        delete to_delete;
    }
}

removeBefore()犯了类似的错误。它没有考虑p.prev在输入时可能为NULL的可能性(当p是列表中的第一个节点时),或者甚至可能是列表的头节点。它看起来应该是这样的:

void DoublyLinkedList::removeBefore(DListNode *p)
{
    DListNode *to_delete = p->prev; //Get to the node before p that is to be deleted

    if (to_delete != NULL)
    {
        if (to_delete->next != NULL) {
            to_delete->next->prev = to_delete->prev;
        }

        if (to_delete->prev != NULL) {
            to_delete->prev->next = to_delete->next;

        // update the head pointer if to_delete is the head node...

        if (header == to_delete) {
            header = to_delete->next;
        }

        delete to_delete;
    }
}

话虽如此,通过集中逻辑可以更好地实现逻辑,例如:

void DoublyLinkedList::remove(DListNode *p)
{
    if (p = NULL) return;

    if (p->next != NULL) {
        p->next->prev = p->prev;
    }

    if (p->prev != NULL) {
        p->prev->next = p->next;
    }

    if (header == p) {
        header = p->next;
    }


    if (trailer == p) {
        trailer = p->prev;
    }

    delete p;
}

void DoublyLinkedList::removeAfter(DListNode *p)
{
    remove(p->next);
}

void DoublyLinkedList::removeBefore(DListNode *p)
{
    remove(p->prev);
}

话虽这么说,一旦你理解了双链表是如何工作的,你就应该抛弃所有这些代码,而只使用STL std::list类,这是一个标准的双链表实现。