题目:试编写算法将带头结点的单链表就地逆置,所谓“就地”是指辅助空间复杂度为O(1)。
关键字:带头结点的单链表+就地逆置
思路1
就地逆置:依次摘下每个结点,利用头插法重接接回L
1.将头结点摘下,
需要变量:L
2.从第一结点开始,依次插入到头结点后面(头插法)直到最后一个结点为止
需要变量:遍历工作指针p,(像个牙签似的,一次一次把串串上的羊肉挑到另一个串串上) 后继指针r(防止断链,即找不到原来的羊肉串串)
LinkList Reverse_1(LinkList L){
LNode*p,*r;//p为工作指针,r为p的后继,以防断链
p=L->next;//从第一个元素结点开始
L->next=NULL;//先将头结点L的next域置为NULL
while(p!=NULL){//依次将元素结点摘下
r=p->next;//暂存p的后继
p->next=L-next;//将p的结点插入到头结点之后
L-next=p;
p=r;
}
return L;
}
思路2
依次直接把每个结点的指针从指向后继结点改为指向前驱结点。
假设pre、p和r指向3个相邻的结点,如下图所示。
假设经过若干操作后,*pre之前的结点的指针都已调整完毕,它们的next都指向其原来的前驱结点。
现在令 *p结点的next域指向 *pre结点,注意到一旦调整指针的指向后, *p的后继结点的链就会断开,为此需要用r来指向原 *p的后继结点。
处理时需要注意两点:(其实就是最终链表“头”和“尾”的妥善处理)
1.在处理第一个结点时,应将其next域置为NULL,因为它将作为新表的尾结点。
2.在处理完最后一个结点后,需要将头结点的指针指向它。
LinkList Reverse_2(LinkList L){
LNode *pre,*p=L->next,*r=p->next;
p->next=NULL;//处理第一个结点,它的最终命运是成为最后一个结点,所以指向NULL
while(r!=NULL){//r为空,则说明p为最后一个结点
pre=p;//依次继续遍历
p=r;
r=r->next;
p->next=pre;//指针反转
}
L->next=p;//处理最后一个结点
return L;
}