双向链表中要删除的节点的成员变量要初始化为null的原因
The reason why the member variable of the node to be deleted from the doubly linked list should be initialized to null
public class Node<E> {
E data;
Node<E> left;
Node<E> right;
}
下面的代码从双向链表中删除特定索引处的节点。在代码的最后,要删除的节点的left、right、data都要初始化为null。这是一个必要的过程吗?如果不初始化为 null
会发生什么
public void remove(int index) {
Node foundNode = findNode(index);
Node leftNode = foundNode.left;
Node rightNode = foundNode.right;
leftNode.right = rightNode;
rightNode.left = leftNode;
foundNode.left = null;
foundNode.right = null;
foundNode.data = null;
--size;
}
完全清楚:new Node()
会将节点字段 left
和 right
初始化为 null
。
remove
将删除的 foundNode
的所有字段设置为 null
是 误入歧途的 尝试 优化 垃圾回收。
您没有创建延迟对象(其他已删除的节点),没有内存泄漏。作为垃圾收集器可以处理无法访问的对象的集合。
注意:对于其他语言,这可能不成立。
在“正常”情况下,最后三个带 null
的赋值是不需要的。当函数完成时,它的局部变量被释放,因此通常不会有任何对 foundNode
.
引用的节点的引用
然而,可能是在其他代码中——不是这个函数的一部分——仍然有一个引用那个节点的变量,然后指示这个节点不再是函数的一部分也不是那么糟糕一个(更长的)列表。通过将 left
和 right
设置为 null
,为每个 node
维护以下不变量:
- 或者
node.left == null
,或者
node.left.right == node
...类似地:
- 或者
node.right == null
,或者
node.right.left == node
如果我们不设置 foundNode.left = null
,则不会恢复上述不变量,如果在函数执行上下文之外仍然存在对 foundNode
的引用,这可能是一个问题。
至于foundNode.data = null
:那真的没有必要。如果foundNode
引用的节点没有被其他地方引用,那么foundNode
可以被垃圾回收。如果也没有其他对其数据的引用,那么该数据也可以被垃圾收集。将此 属性 设置为 null
并不会真正改变该过程。其次,如果我们考虑仍然可能有对该节点的引用的情况,那么 null
可能是在整个算法中 实际上 有意义的数据,因此将其设置为null
不保证以明确的方式将其标记为“已删除”节点。
public class Node<E> {
E data;
Node<E> left;
Node<E> right;
}
下面的代码从双向链表中删除特定索引处的节点。在代码的最后,要删除的节点的left、right、data都要初始化为null。这是一个必要的过程吗?如果不初始化为 null
会发生什么public void remove(int index) {
Node foundNode = findNode(index);
Node leftNode = foundNode.left;
Node rightNode = foundNode.right;
leftNode.right = rightNode;
rightNode.left = leftNode;
foundNode.left = null;
foundNode.right = null;
foundNode.data = null;
--size;
}
完全清楚:new Node()
会将节点字段 left
和 right
初始化为 null
。
remove
将删除的 foundNode
的所有字段设置为 null
是 误入歧途的 尝试 优化 垃圾回收。
您没有创建延迟对象(其他已删除的节点),没有内存泄漏。作为垃圾收集器可以处理无法访问的对象的集合。
注意:对于其他语言,这可能不成立。
在“正常”情况下,最后三个带 null
的赋值是不需要的。当函数完成时,它的局部变量被释放,因此通常不会有任何对 foundNode
.
然而,可能是在其他代码中——不是这个函数的一部分——仍然有一个引用那个节点的变量,然后指示这个节点不再是函数的一部分也不是那么糟糕一个(更长的)列表。通过将 left
和 right
设置为 null
,为每个 node
维护以下不变量:
- 或者
node.left == null
,或者 node.left.right == node
...类似地:
- 或者
node.right == null
,或者 node.right.left == node
如果我们不设置 foundNode.left = null
,则不会恢复上述不变量,如果在函数执行上下文之外仍然存在对 foundNode
的引用,这可能是一个问题。
至于foundNode.data = null
:那真的没有必要。如果foundNode
引用的节点没有被其他地方引用,那么foundNode
可以被垃圾回收。如果也没有其他对其数据的引用,那么该数据也可以被垃圾收集。将此 属性 设置为 null
并不会真正改变该过程。其次,如果我们考虑仍然可能有对该节点的引用的情况,那么 null
可能是在整个算法中 实际上 有意义的数据,因此将其设置为null
不保证以明确的方式将其标记为“已删除”节点。