【问题标题】:Inserting before and after a node在节点之前和之后插入
【发布时间】:2017-07-31 22:24:07
【问题描述】:

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

        // 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,但是当函数结束时,析构函数中出现分段错误,说明正在删除的节点未分配。

【问题讨论】:

  • "if(&p == NULL) " - 指针可以为空,但对象的地址永远不能为空,这里&amp;p是现有对象的地址。跨度>
  • 啊,好吧,我将更改引发的异常的措辞。谢谢你
  • Kate,一般来说,我们在代码中发现错误的方式并不是认真思考它。甚至不是通过将代码展示给其他可能更努力思考的人。我们在代码中发现错误的方法是使用调试器。我想最终可能会有人出现,他能够指出您的代码中的错误,但是如果您只使用调试器,您会为自己节省大量时间(并学习一项非常有价值的技能)。
  • 不,Neil 的意思是您需要摆脱整个 if() 语句以及抛出异常。它永远不会发生。
  • 我已经使用了我的调试器和 insertAfter 函数,我用更新的代码表明一切都指向正确的方向。

标签: c++ linked-list insert


【解决方案1】:

链表是一个指针列表。您列表的 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 类,这是一个标准的 double -链表实现。

【讨论】:

  • 您的代码给了我与原始代码相同的问题。这是我注意到的另一件事。我首先调用 insertAfter 并打印列表并且它没有更改。然后我调用 insertBefore 并打印列表,使用 insertAfter 后应该发生的更改现在与 insertBefore 更改一起可见,但是最后我在析构函数中遇到了分段错误。我已经使用了我的调试器,它不在析构函数中,而是 insertAfter 和 insertBefore 的一些问题
  • @Kate 链表是一个指针列表,但你并没有像我告诉你的那样将 headertrailer 更改为指针。对于链表实现,这非常重要。通过引用传递节点也是不习惯的,但无论如何你都在这样做。我不想早点说什么,但你真的应该用指针传递它们。
猜你喜欢
  • 1970-01-01
  • 2011-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多