**
1.错误:
**
在作者刷题时,遇到了一个情况,需要用到两个链表去完成一个操作:用first指针储存链表p的首元素的地址,用于做return(函数返回链表首地址),在这个过程中,p在不断的扩展,接收新元素。
以下是错误代码:
ListNode *mergeTwoLists(ListNode * l1, ListNode * l2) {
ListNode *p, *first = new ListNode;
int count = 0;
do {
//此处代码忽略,即p链表扩充的操作,与总结无关
if (count++ == 0) first = p; //p得到第一个元素之后,把这个元素地址给first储存下来
p = p->next; //p向后挪一位,下次循环继续扩充
} while (l1 != nullptr || l2 != nullptr);
return first;
}
我当时敲出这段代码,觉得没有任何问题,因为我的想法是,在p接收了第一个元素之后,first = p,将p的地址保存在first中了,接下来要继续扩充,肯定要进行链表中非常常规的操作:p = p->next,然后,在下一次循环中,因为p->next地址和first->next地址是一样的,下次将下一个元素赋给p,相当于赋给上一个p的next,也就是赋给first的next,这样p和next都在扩充。(后来验证这是错误的,因为只有p在扩充,而first纹丝不动)
2.改正:
为什么会出现这种情况?即first不会跟随p的扩充而扩充,p和first的地址不是一样的吗?
仔细想了一下,发现自己把指针之间的赋值的概念给搞混淆了。
在这个例子中,p->next中储存的地址和其自己的地址是两个东西,我用p = p->next,是把p->next中储存的地址给p,而不是把&p->next(其自己的地址)给p,所以当下一次给p赋值时,只是把p->next中传给p的地址覆盖了,而不是直接改变上一个p->next中储存的地址,所以也没有办法改变first->next中储存的地址。
那么,如果要通过其他指针间接改变first->next中的地址,还是应该用双重指针接first->next的地址,并直接对该地址储存的值进行操作,例如:
ListNode ** addr,*first;
addr = &first->next;
*addr = new ListNode;
这样就可以通过二重指针addr间接扩充first链表了。
可是,一般来说,最好不要用双重指针,这样会特别麻烦。遇到这样的复杂情况,可以多走几步,尽量用p->next直接接下一个元素的地址进行链表扩充。