1 STU *invert(STU *head){ 2 STU *new_head=NULL,*p1,*p2,*new; 3 do{ 4 for(p1=head;p1->next!=NULL;p1=p1->next) 5 p2=p1; 6 if(new_head==NULL) 7 { 8 new_head=p1; 9 new_head->next=p2; 10 } 11 else 12 { 13 new->next=p2; 14 } 15 new=p2; 16 p2->next=NULL; 17 }while(head->next!=NULL); 18 return new_head; 19 }
完整的代码我就不贴了,只贴用来进行逆序的函数。链表的新建和输出在前面的博客里可以找到。
谭浩强答案书上的答案可能是印刷错误,调试不出答案,我揣摩答案的思路重新整理了一下函数。
算法的思路是这样的:
第1次循环:
找到链表的最后一个结点p1和倒数第二个结点p2;
把p1当作新链头(Line 8),p2当作新链的第二个结点(Line 9),也是新链中最新的结点(Line 15);
把原来链表的最后一个结点删去(Line 16)。
这次循环完成之后,原来链表的结点少了一个,新链表的结点多了两个。
第2次循环:
找到链表的最后一个结点p1和倒数第二个结点p2,此时的p1是原先的倒数第二个结点,p2是原先的倒数第3个结点;
把p2连接在新链表的后面(Line 13),此时p2是新链中最新的结点(Line 15);
再从原来的链表删去一个结点(Line 16)。
这次循环完成之后,原来链表的结点少了一个,新链表的结点多了一个。
……
从第2次循环开始,每次是把链表中的倒数第二个结点加入到新链中。当head->next==NULL时,链表中只有一个结点,没有倒数第二个结点,所以循环结束,新链表已经产生。最后一次循环过程中,p1是指向最初链表的第二个结点,p2指向最初链表的头结点,把p2加入到新链中,同时使p2->next=NULL,成为新链的链尾。
如果知道链表的长度len的话,可以用以下更容易理解的代码:
1 STU *invert(STU *head){ 2 STU *new_head=NULL,*p1,*p2,*new; 3 int i; 4 for(i=0;i<len;i++) 5 { 6 p2=head; 7 for(p1=head;p1->next!=NULL;p1=p1->next) 8 p2=p1; 9 if(new_head==NULL) 10 new_head=p1; 11 else 12 new->next=p1; 13 new=p1; 14 p2->next=NULL; 15 } 16 return new_head; 17 }
循环len次,每次把链表末尾的结点加入到新链表。Line 6的目的是预防链表中只有一个结点时,p2的值为不确定的值的情况。