有关Java链表概念的有趣问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qilei2010/article/details/51226866

题目


void print(){
    for(ListNode node = head; node != null; node = node.next){
        System.out.print(node.val);
        System.out.print("->");
        System.out.print("null");
    }
}
void main(){
    ListNode node1 = new ListNode(1);
    ListNode node2 = new ListNode(2);
    ListNode node3 = new ListNode(3);

    ListNode head = node1;
    node1.next = node2;
    node2.next = node3;

    print(head);//语句1

    node1= node2;
    print(head);//语句2
}
//如语句1会输出:123
//那么请问语句2输出什么?

(此题不难,但很考链表概念,愿君花2分钟认真思考后,再看下文)


答案解析

乍看之下,大多认为输出23,我初答也认为是 23,其实不然,答案却是123。
下面以图讲明。

首先须知 Java 中除基本类型外,多是引用类型。所谓引用,类似于内存地址编号。

简单解释:
node1变量指向节点2

详细解释:
node1=node2前后各变量的值及内存地址变化图

不管node1 node2指来指去,指向哪个节点,都不影响链表遍历结果。因为遍历时,根本没有使用到node1 node2
node3
这三个打酱油的变量。

若看图能懂,下文可不必费时去看。


错误解析

犯错的原因是:将node1 = node2 理解为 节点1整个变成了和节点2一样(val和next都是节点2对应的复制品),所以遍历起来就是 (head)node2 -> node3输出23。
注意:这里node1 = node2改变的只是node1 node2的值,并未影响到节点本身。
若是 node1->next = node2 -> next ,输出才会变成 13(没有了2),想想为什么?

变与不变

其实node1node2二变量(的值)无论如何变化,均未影响到图中右侧黑色的链表实体结构,因它二者只是链表内节点的别名而已,弃之也可。
对于本题,print()方法每次均从head开始使用node.next指针来遍历链表,并未使用到node123等各节点的别名变量。所以任node1 = node2,并不影响输出结果。

引用赋值的理解

head = node1node1 = node2如何理解?
变量赋值,无论变量类型怎样,均是以右值赋给左值。

int a = 2, b = 3;
a = b;
//a 变为 3 , b 仍是 3

虽然head、node1、node2 是引用类型变量,原理和基本类型相仿,不过他们的值不再是简单的数字,他们的是一个地址编号

    head = node1;
//0x0001   0x0001    <-变量的值
//  节点1   节点1     <-指向的节点

    node1, node2;
//0x0001   0x0003
//  节点1  节点2
    node1 = node2;
//0x0003   0x0003
//  节点2  节点2

head = node1 ,是将node1的值(它存储的地址编号)0x0001赋值给head,所以head的值变为了0x0001,也即指向了链表第一个节点。
同理,node1 = node2后,node1的值变成了0x0003,指向了链表的第2个节点。

但,不管node1 node2指来指去,指向哪个节点,都不影响链表遍历结果。因为遍历时,根本没有使用到node1 node2 node3这三个打酱油的变量。

猜你喜欢

转载自blog.csdn.net/qilei2010/article/details/51226866