「这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战」
今天说一下两两交换链表中的节点的问题
实现思路
两两交换链表中的节点,交换的是链表种的地址,而不是每个链表节点中的值。
使用递归思路实现,那么就要考虑边界问题,也就是说什么时候不需要继续递归下去了。
两两交换节点,那么如果节点数为奇数的话,最后一个节点肯定没办法交换;另外如果链表交换完成的话,也就是最后链表中没有节点也没有办法完成交换。
所以当链表 $head = null 时(链表为空) 或者 $head->next = null 时(链表节点数为奇数),需要退出递归循环。
那么接下来如果两两交换链表节点呢?节点交换位置,实际上操作的是链表中 next指针的指向。
如果链表中有两个节点,我们把第二个节点指向第一个节点,即原链表第二个节点变成了新链表的第一个节点(头节点)。此时,原链表的第一个节点需要代替原链表中第二个节点。当链表只有两个节点时,原链表的第一个节点的next指向null,但是如果有多个节点时,那么原链表的第一个节点就需要指向下一个节点,但是下一个节点还没有完成位置交换,所以需要等待下一个节点完成交换后,原链表的第一个节点才能指向下一个节点。
两两交换时,实际上,原链表的第二个节点指向原链表的第一个节点,原链表的第一个节点需要指向原链表的第三个节点,即原链表的第二个节点的下一个节点,以此类推。
在递归过程中, 每次只交换当前节点和下一个节点,然后当前节点的指向等待再次循环返回。
完整代码
第455-457行代码,当前节点为空,即链表剩余节点为空,或者当前节点的下一个节点为空,则返回当前节点。
第459行代码,我们把当前节点的下一个节点,赋值给一个变量,即把链表中的第二个节点提出来,当作新链表的头节点。
第460行代码,由于原链表中的第一个节点交换位置后的next指向暂不确定,需要再次循环。由于当前链表中的第一个和第二个节点已经交换,所以需要把第三个节点地址递归使用,即 $first = $head->next, $first就是第二个节点,那么 $first->next就是第三个节点,即 $head->next->next。
第461行代码,上一行代码中,原链表的第一个节点的next指向已经有了返回值,然后我们再把交换后的新链表中第一个节点和第二个节点相连接即可。
第462行代码,返回新链表$first。