既然链表逆序输出可以用递归方法实现,单链表反转也可以采用递归思想实现。
不同的地方时,后者需要破坏原有的链表结构
不晓得采用1个指针能不能实现
先考虑用2个指针p,q分别记录原来的链表关系
初始时:p = NULL,q = head; 特殊条件为q==NULL,表示链表中没有元素,这也可以作为递归结束条件(这可以成为一种找递归结束条件的思路)
递归处理操作是:p=q;q=q->next;linkList_reverse_recur(p,q) 如果这里q==NULL,说明p为最后一个元素,p即为反转后的链表表头
核心处理操作是:q->next = p
不对
如果是递归的话,在核心处理部分开始的时候,原有的链表结构为被打乱,也就不需要用一个额外的指针记录前一个节点指针,
用1个指针p开始递归,p初始为p=head,结束应该是p->next == NULL 考虑到head==NULL的特殊情况,这也应该放到递归结束条件里去
核心处理为:p->next->next = p; 因为虽然递归的因子是p,但实际上处理的是p->next的后继指针,所以p->next == NULL 为结束条件 当然为了保证逆序,该处理 要放在递归操作之后
递归操作:linkList_reverse_recur(p->next)
关于递归函数的返回值,这个其实没关系,因为我只要保证最后一层的返回结果就行了。但因为递归还要进行出栈,所以这里不能return,因此必须增加一个参数来保存反转后表头的位置
执行程序的时候出现无限循环,原来是第一个元素没有处理,导致第一个元素和第二个元素徐成一个链循环,不停的打印8和9
要对一个元素和最后一个处理的第一个元素进行单独处理,那么如何判断一个元素是那个元素,只能通过指针判断,因此必须加一个参数来说明原来表头指针oldhead,通过判断p==oldhead来进行处理
核心代码:
int linkList_reverse_recur(struct node *oldhead,struct node* &newhead,struct node *p) //三个参数是必须的,见前面的分析
{
if(p == NULL) //链表为空的特殊情况处理,仅在第一次递归时判断一次,后续的递归不可能出现这种情况,切记这一点
return 0;
if(p->next != NULL)
{
linkList_reverse_recur(oldhead,newhead,p->next);
p->next->next = p; //核心处理,此时顺序的链表结构尚未被破坏
}
else
{
newhead = p;
}
if(p == oldhead) //放在最后,单独处理第一个元素
p->next = NULL;
}
OVER!!!