在节点之前和之后插入

时间:2017-07-31 22:24:07

标签: c++ linked-list insert

我有以下两个功能,它们根本不会改变我的链接列表。我考虑到如果给定节点为空,我然后检查给定节点是头还是尾,然后我插入需要的地方并更正节点指向的位置。我必须错过一小部分,但我不确定是什么。有任何想法吗?谢谢!

        // 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;
    }
}

This shows the debugger for the insert after function

我有一个最初的列表:

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,但是当函数结束时,析构函数中存在一个段错误,表示正在删除的节点未被分配。

1 个答案:

答案 0 :(得分:0)

链表是指针列表。您的列表的headertrailer字段需要是DListNode*个指针,而不是DListNode个对象实例。如果它们不是指针,它们就无法列出管理。

您的代码未正确更新p节点周围的节点。即使您必须更新headertrailer字段,您仍然必须更新其他节点。但你不是那样做的。

通过引用传递节点也不习惯,但无论如何你都是这样做的。我之前并不想对此说些什么,但你真的应该用指针传递它们。

您的代码看起来应该更像这样:

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类,这是一个标准的双链表实现。