单链表反转原理(执行步骤)
Node reverseList(Node H)
{
if (H == NULL || H.next == NULL) //链表为空或者仅1个数直接返回
return H;
Node p = H, newH = NULL;
while (p != NULL) //一直迭代到链尾
{
Node tmp = p.next; //暂存p下一个地址,防止变化指针指向后找不到后续的数
p.next = newH; //p.next指向前一个空间
newH = p; //新链表的头移动到p,扩长一步链表
p = tmp; //p指向原始链表p指向的下一个空间
}
return newH;
}
解释:
先假设一个为3个,而且它们的存储地址已知。为了方便讲解,假设p指针已经移动到上图所示的位置。
此时newH为指向2所在的位置,即newH为201(2的存储地址是201-205,表示为201)。
p是表示节点3,p.next是表示节点3所指向的下一空间,即p.next为401;
代码 Node tmp = p.next; //暂存p下一个地址,防止变化指针指向后找不到后续的数
表示将节点3的指向空间先暂时保存起来,即tmp 为 地址401。
节点3本来是指向节点4的,要想反转,就应该让节点3指向节点2的存储空间,即
代码 p.next = newH; //p.next指向前一个空间
让指正p所指向的结点3的引用值改为newH的,让p.next等于newH,就是让节点3指向了节点2。
新链表移动:接下来为了考虑到下一次的循环,所以我们得让新的链表能继续变长,所以得移动新链表的头指正,本来newH是指向节点2的,现在节点3已经指向了节点2,说明节点3已经被并入到新的链表了,所以我们得将新链表的头指针移动到链表3中,所以令newH等于p,此时头指针指向节点2的指向关系被去除了,被指向节点3这个指向关系代替了。
newH = p; //新链表的头移动到p,扩长一步链表
旧链表指针移动:为了能接着读取旧链表的下一个节点,我们需要将p指针移动到下一节点,所以用下面这行代码完成赋值。
p = tmp;
然后接着进行循环判定,因为p是节点4,不是空的,所以接着执行循环里面的操作。
可能的疑惑点:
①为什么最后一句代码是p = tmp;,而不是p.next = tmp呢?
答:因为我们要想让指针p指向某个节点,只需令p 等于改节点的的地址,
②为什么移动新链表是newH = p;,而不是newH = p.next呢?
答:关于这点,我的猜测是想要指针指向某个节点,可以通过让这个指针等于另一个指针p(p指针是指向该节点的),或者让这个指针等于另一个节点的存储位置。