c++ - 尝试在双向链表的中间插入新节点时我是否连接错误?

标签 c++ pointers data-structures doubly-linked-list

结构看起来像:

class DList{
private:
        struct Elem {
        Elem *prev, *next;
        };
        Elem *_head, *_tail;
}

现在我有两个现有节点:cur 和 cur->next,我想在它们之间插入一个新节点。这是我所做的:

    cur->next = ins;//step-1-1 cur
    ins->prev = cur;//step-1-2 cur

    ins->next = cur->next;//step-2-1 cur->next
    cur->next->prev = ins;//step-2-2 cur->next 

问题是在我的程序的进一步遍历循环中,我的指针无法再到达 _tail。我是不是在我的插入部分弄错了什么? (一旦我在上面的中间代码处评论插入,循环就完美地工作了)

最佳答案

是的,这里有一个接线错误。让我们画画吧!

想象一下事情看起来像这样,最初:

             curr
              |
              v
         +----------+                         +----------+
         |   next   | ----------------------> |   next   | --> ...
         +----------+                         +----------+
 ... <-- |   prev   | <---------------------- |   prev   | <-- ...
         +----------+                         +----------+
                           +----------+
                           |   next   |
                           +----------+
                           |   prev   |
                           +----------+
                                ^
                                |
                                ins

首先,您执行 cur->next = ins;,它会执行以下操作:

             curr
              |
              v
         +----------+                         +----------+
         |   next   | -----------+            |   next   | --> ...
         +----------+            |            +----------+
 ... <-- |   prev   | <----------+----------- |   prev   | <-- ...
         +----------+            v            +----------+
                           +----------+
                           |   next   |
                           +----------+
                           |   prev   |
                           +----------+
                                ^
                                |
                                ins

请注意,我们不再有指向原先位于 curr 之后的元素的指针 - 糟糕!这将是一个问题。

现在,我们执行 ins->prev = curr;,如下所示:

             curr
              |
              v
         +----------+                         +----------+
         |   next   | -----------+            |   next   | --> ...
         +----------+            |            +----------+
 ... <-- |   prev   | <----------+----------- |   prev   | <-- ...
         +----------+            v            +----------+
               ^           +----------+
               |           |   next   |
               |           +----------+
               +---------- |   prev   |
                           +----------+
                                ^
                                |
                                ins

现在,我们编写 ins->next = curr->next;。但是哎呀!注意 curr->next 指向 ins,所以我们只是在这里添加了一个循环:

             curr
              |
              v
         +----------+                         +----------+
         |   next   | -----------+            |   next   | --> ...
         +----------+            |            +----------+
 ... <-- |   prev   | <----------+----------- |   prev   | <-- ...
         +----------+            v            +----------+
               ^           +----------+
               |           |   next   | --+
               |           +----------+   |
               +---------- |   prev   | <-+
                           +----------+
                                ^
                                |
                                ins

最后,您编写 cur->next->prev = ins; 但是哎呀! curr->next 仍然是 prev,所以我们得到另一个循环:

             curr
              |
              v
         +----------+                         +----------+
         |   next   | -----------+            |   next   | --> ...
         +----------+            |            +----------+
 ... <-- |   prev   | <----------+----------- |   prev   | <-- ...
         +----------+            v            +----------+
                           +----------+
                       +-> |   next   | --+
                       |   +----------+   |
                       +-- |   prev   | <-+
                           +----------+
                                ^
                                |
                                ins

这里的问题是,在第一次赋值后,您无法跟踪 curr->next 指向的单元格,因此您无法找到正确的位置。

如果你开始写这样的东西会怎样?

DList* next = curr->next;

然后在某些上下文中使用 next 而不是 curr->next

关于c++ - 尝试在双向链表的中间插入新节点时我是否连接错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46638127/

相关文章:

c++ - 在 C++ 中的指针数组中,内存过度使用是否会导致指针存储在非连续的内存块中?

c - 为什么队列和栈声明为指针?

java - 使用链表实现优先级队列

java - 建议使用哪种数据结构返回两个值

c++ - CMake 链接器无法识别头文件

c++ - 如何在 C++ 中获得最接近平均值的数字?

c++ - 传递一个多态 vector

c++ - 链表作业数组 - 运行时错误

java - 为什么这个 DFS 代码在某些情况下不起作用?

c++ - 模板偏特化和从属名称