双向链表:正确删除并在列表中间添加内容?
Doubly Linked Lists: Properly deleting an adding something in the middle of a list?
Write the code fragment that appropriately deletes the node pointed to by p
(data value 14) in the doubly linked list.
我想我知道如何做到这一点:
(1) 使右边的节点previous
元素指向左边的节点
(2) 使左边的节点next
元素指向右边的节点
(3) 使p
指向NULL的节点元素删除
但是我忘记了如何在代码中编写它(已经有一段时间了)。我在想它会是这样的(我假设 node 是一个包含 int 数据的结构,node* next 和 node* previous):
node* x = p->next;
node* y = p->previous;
x->previous = y;
y->next = x;
p->previous = nullptr;
p->next = nullptr;
delete p;
x->previous = y;
写代码片段在14和16之间插入一个节点(同图):
node *x = p->next;
node y;
y->previous = x->previous;
y->next = p->next;
x->previous = y;
p->next = y;
这样可以吗?
删码差不多就好了。但是,请注意一些事情:
- 您使用的命名不一致(
left
应该是 previous
)。
- 你不需要把
p
的字段设置为nullptr,反正你要删除它。
- 最后一个
x->previous = y
会让这个"circular"不是你想要的!
这将是一个更好的近似值:
node *x = p->next;
node *y = p->previous;
x->previous = y;
y->next = x;
delete p;
但是,这有一个警告:如果列表是单例会怎样?也就是说,您只有 p
?。请注意 p->next
和 p->previous
都将是 NULL
,因此对 x
和 y
的赋值将会出错! (请注意,作为第一个或最后一个元素将导致相同的问题,只是在某些方面)。
第二部分代码有点问题:
- 首先请注意,您的代码无法编译:
y
是一个变量,您要通过 y->
取消引用它。这是一个只能对指针进行的操作[1]。这个问题实际上更深刻,因为 y
被放置在堆栈中,一旦离开范围就会被删除,因此如果您使用 &y
获取指针。
y->previous = x->previous;
可以简化为y->previous = p
y->next = p->next;
可以简化为y->next = x
通过这些更正,这将变成:
node *y = new node();
y->previous = p;
y->next = p->next;
p->next->previous = y;
p->next = y;
但是请注意,这再一次不能处理 p
指向列表末尾的情况! (p->next->previous = y
会发生什么?),所以你应该更正它。另外, p
指向列表的开头而不是结尾是否重要?你应该处理那个吗?
唯一的实际问题是动态内存问题,其余更正只是 'readability' 更正。尽管 'readability' 是个人喜好,但您应该始终尝试使代码尽可能清晰。
[1] 除非你真的在使用 operator->()
重载,我假设你没有。
Write the code fragment that appropriately deletes the node pointed to by
p
(data value 14) in the doubly linked list.
我想我知道如何做到这一点:
(1) 使右边的节点previous
元素指向左边的节点
(2) 使左边的节点next
元素指向右边的节点
(3) 使p
指向NULL的节点元素删除
但是我忘记了如何在代码中编写它(已经有一段时间了)。我在想它会是这样的(我假设 node 是一个包含 int 数据的结构,node* next 和 node* previous):
node* x = p->next;
node* y = p->previous;
x->previous = y;
y->next = x;
p->previous = nullptr;
p->next = nullptr;
delete p;
x->previous = y;
写代码片段在14和16之间插入一个节点(同图):
node *x = p->next;
node y;
y->previous = x->previous;
y->next = p->next;
x->previous = y;
p->next = y;
这样可以吗?
删码差不多就好了。但是,请注意一些事情:
- 您使用的命名不一致(
left
应该是previous
)。 - 你不需要把
p
的字段设置为nullptr,反正你要删除它。 - 最后一个
x->previous = y
会让这个"circular"不是你想要的!
这将是一个更好的近似值:
node *x = p->next;
node *y = p->previous;
x->previous = y;
y->next = x;
delete p;
但是,这有一个警告:如果列表是单例会怎样?也就是说,您只有 p
?。请注意 p->next
和 p->previous
都将是 NULL
,因此对 x
和 y
的赋值将会出错! (请注意,作为第一个或最后一个元素将导致相同的问题,只是在某些方面)。
第二部分代码有点问题:
- 首先请注意,您的代码无法编译:
y
是一个变量,您要通过y->
取消引用它。这是一个只能对指针进行的操作[1]。这个问题实际上更深刻,因为y
被放置在堆栈中,一旦离开范围就会被删除,因此如果您使用&y
获取指针。 y->previous = x->previous;
可以简化为y->previous = p
y->next = p->next;
可以简化为y->next = x
通过这些更正,这将变成:
node *y = new node();
y->previous = p;
y->next = p->next;
p->next->previous = y;
p->next = y;
但是请注意,这再一次不能处理 p
指向列表末尾的情况! (p->next->previous = y
会发生什么?),所以你应该更正它。另外, p
指向列表的开头而不是结尾是否重要?你应该处理那个吗?
唯一的实际问题是动态内存问题,其余更正只是 'readability' 更正。尽管 'readability' 是个人喜好,但您应该始终尝试使代码尽可能清晰。
[1] 除非你真的在使用 operator->()
重载,我假设你没有。