链表重组代码中:为何修改curr指针无法更新node节点?
问题背景
我正在编写用于重组链表的代码,该代码以交替方式从链表首尾取节点,将1->2->3->4->5->6转换为1->6->2->5->3->4。以下是原地重组链表的核心代码片段,我的疑问集中在合并阶段的指针操作:
Node curr=node; while (node1 != null || node2 != null) { // First add the element from first list if (node1 != null) { curr.next = node1; curr = curr.next; node1 = node1.next; } // Then add the element from second list if (node2 != null) { curr.next = node2; curr = curr.next; node2 = node2.next; } }
调试时发现:当curr指向node时,执行curr.next = node1会使node发生变化,但执行curr = curr.next时node却没有变化,请问这是为什么?
原因解释
这是Java中引用类型的赋值与修改的本质差异导致的,分两步拆解:
curr.next = node1时node变化的原因
此时curr和node指向同一个Node对象(也就是代码里创建的dummy节点new Node(0))。curr.next = node1是在修改这个共享对象的内部属性——你操作的是该Node对象的next字段,而node同样指向这个对象,所以查看node时,它的next属性自然会跟着改变,因为你改的是对象本身,不是指针变量。curr = curr.next时node不变的原因curr = curr.next是给curr这个引用变量重新赋值:此时curr不再指向原来的dummy节点,而是指向curr.next对应的那个Node(也就是node1的第一个节点)。但node这个引用变量仍然指向原来的dummy节点,两者现在指向不同的对象,所以修改curr的指向不会影响node的指向。
简单总结:
- 修改引用变量指向的对象内部属性,会影响所有指向该对象的引用;
- 给引用变量重新赋值新的对象地址,只会改变当前变量的指向,和其他引用无关。
额外补充
代码最后执行的node = node.next,是把node的指向从dummy节点切换到重组后的链表头节点,这也是单独的引用赋值,不会影响其他变量,只是让node指向新的链表起点。
内容的提问来源于stack exchange,提问作者srinjay ayan

