为什么对象的值会发生变化,即使它具有不同的引用?

Why object's value changes even though it has different references?

我对这里的对象引用感到困惑。合并2个排序链表是LC问题

我知道在第一次迭代时 current.nextresult 引用了同一个对象,所以当我将新值分配给 current.next 时,result 值也会发生变化。

在第二次迭代时,r1 和 r2 均为假,因此 result, current and current.next 指向不同的对象。

我不明白的是为什么为当前 (current = current.next) 分配新值不会修改结果对象但 current.next = l1/l2 会?

有人可以给我解释一下吗?

public static ListNode MergeTwoLists(ListNode l1, ListNode l2)
        {
            if (l1 == null) return l2;
            if (l2 == null) return l1;
            if (l2 == null && l1 == null) return null;

            ListNode result = new ListNode(0);
            ListNode current = result;

            while (l1 != null && l2 != null)
            {
                var r1 = Object.ReferenceEquals(result, current);
                var r2 = Object.ReferenceEquals(result, current.next);
                
                if (l1.val < l2.val)
                {
                    current.next = l1;
                    l1 = l1.next;
                }
                else
                {
                    current.next = l2;
                    l2 = l2.next;
                }

                current = current.next;
            }

            // l1 is lognger than l2 
            if(l1 != null)
            {
                current.next = l1;
                l1 = l1.next;
            }

            // l2 is lognger than l1 
            if (l2 != null)
            {
                current.next = l2;
                l2 = l2.next;
            }

            return result.next;
        }
public class ListNode
    {
        public int val;
        public ListNode next;
        public ListNode(int x = 0, ListNode next = null)
        {
            val = x;
            next = null;
        }
    }

编辑

假设我们有这些:

Input: l1 = [1,2,4], l2 = [1,3,4]    Output: [1,1,2,3,4,4] 

第一次迭代:

r1 = true,结果和当前都指向同一个对象。

r2 = false

l1.val == l2.val 所以我们执行

else
{
  current.next = l2;
  l2 = l2.next;
}

此刻我们有: result = [0,1,3,4]current = [0,1,3,4], l2 = [3,4]

接下来我们执行 current = current.next,所以 current = [1,3,4] 它不再指向结果。

第二次迭代

r1 = false,结果和当前指向不同的对象。

r2 = false,

l1.val < l2.val 所以我们执行

if (l1.val < l2.val)
{
    current.next = l1;
    l1 = l1.next;
}

此刻我们有:

result = [0,1,1,2,4], current = [1,1,2,4], l2 = [3,4], l1 = [2,4]

这是我不明白的部分:结果和当前指向不同的对象,但当前更改结果也是如此。结果如何保持对当前的引用??

接下来我们执行current = current.next,所以current = [1,2,4],所以我们修改current但是这次结果没有改变。

您永远不应将 current.next 分配给 l1l2 中的节点。相反,您必须创建一个与 l1l2 具有相同值的新 ListNode,并使 current.next 指向您的新 ListNode。否则,你正试图拉直一碗意大利面,这是一项不可能完成的任务。你需要制作你自己的新意大利面条。

Result and current point to diffrent objects, still when current changes result does as well. How result keeps reference to current?

看看你问题的这一部分:

so current = [1,3,4] and it doesn't point to result anymore.

重要的是,该列表 中的 1result = [0,1,3,4] 中的 1 是相同的元素 。如果您修改 1 节点的 next 字段,您将修改该节点所属的任何列表。包括 result 正在引用的列表。

稍后您写:

At this moment we have:

result = [0,1,1,2,4], current = [1,1,2,4], l2 = [3,4], l1 = [2,4]

请注意 result 指向的列表 current 指向的列表 不同。但是在第一个节点之后, 是一样的。

第一次迭代后,result.next 引用了与 current 相同的对象。这是因为 resultcurrent 开始引用同一个对象,然后作为第一次迭代的最后一步, current 被更改为引用 current.next。因为 currentresult 在那个点上是一样的,所以 current.nextresult.next 也是一样的。所以把current改成current.next后,就和设置成result.next一样了。

所以在第二次迭代中,result.nextcurrent 是相同的。这意味着当您修改 current.next 时,这与修改 result.next.next 相同,其效果是用新链替换 result 列表中前两个元素之外的内容l2 引用的元素。

同样:这里的关键是每个变量都简单地指向一个节点。可以将其概念化为指向节点列表,但前提是您要记住,如果您修改该列表中任何节点的 next 字段,即使变量未引用,您也会修改整个列表引用列表根的变量。