C#单链表InsertDataAtTheEnd、DelteNodeByValue方法运行逻辑疑问
C# 单链表引用类型操作逻辑解答
核心前提:C# 引用类型的本质
C#中使用class关键字定义的类型都是引用类型,你代码中的Node就是class,因此所有Node类型的变量存储的都不是节点对象本身,而是堆内存中节点对象的内存地址,你可以把它理解为指向真实对象的"指针"。
要区分两种操作的本质差异:
- 修改变量本身的值:比如
temp = temp.next,只是把temp变量存储的地址改成下一个节点的地址,不会修改任何链表节点的实际内容 - 修改变量指向的对象的成员:比如
temp.next = newNode,是直接修改temp指向的堆中真实节点的next属性,会直接改变链表的结构
疑问1:InsertDataAtTheEnd方法修改temp.next为什么会影响head?
我们逐行拆解执行逻辑:
Node temp = head;:把head存储的头节点地址复制给temp,此时temp和head指向堆中同一个头节点对象,链表本身没有任何变化while (temp.next != null) { temp = temp.next; }:循环过程中只是不断把temp变量的地址修改为下一个节点的地址,相当于temp这个"指针"不断往后移动,直到指向链表的最后一个节点(此时最后一个节点的next为null),整个过程没有修改任何节点的内容temp.next = newNode;:此时temp指向的是链表的最后一个节点(属于head对应的链表的一部分),修改它的next属性就是直接修改堆中这个节点的内容,相当于给原链表的最后一个节点挂上新的节点,自然会影响整个head链表
疑问2:DelteNodeByValue方法的运行原理
逐行拆解逻辑:
- 首先判断头节点是不是要删除的目标:如果头节点的值匹配,直接
head = temp.next,把头指针指向第二个节点,原头节点就脱离链表完成删除 - 循环查找目标节点:
previously变量始终存储当前节点的前一个节点的地址,temp存储当前遍历到的节点的地址,这个过程只是移动两个"指针",不会修改节点内容 - 找到目标节点后的操作:
previously.next = temp.next,是直接修改前一个节点的next属性,让它跳过当前节点直接指向当前节点的下一个节点,这样当前节点就从链表的链路中被移除,完成删除操作
简易类比理解
你可以把每个节点想象成带门牌的房间,每个房间里有一张纸条写着下一个房间的门牌:
- head是写着头节点门牌的纸条
- temp是你手里的便签,你抄下head上的门牌,然后挨个跑房间,每次把便签上的门牌改成当前房间里纸条写的下一个门牌,这个过程不会改任何房间里的纸条
- 等你找到目标房间,你修改这个房间里的纸条内容,那整个房间的串联关系自然就变了,和你手里的便签没有关系
内容的提问来源于stack exchange,提问作者thomas_cl
相关产品推荐
相关产品推荐

