单链表逆转方法有很多:
这里谈两种:
1.再建一个链表然后,边遍历原来的链表,便是用头插法,完成新的单链表,这样子虽然内存损耗比较大,但是也是勉强可以完成的。
2.使用3个指针,逐个节点的逆转。
p q两个指针分别指向想要逆转关系的两个节点,
p指向前一个节点,q指向后一个节点
r指向q后余下的链表。
具体操作:
这里我们忽略头节点,也是说连带头节点一起逆转。
初始化操作:
p=L;
q=p->next;
p=NULL;
这里我们先让p指向第一个节点,q指向第二个节点。然后解开他们之间的关系
让第一个的节点的next指向NULL,以便后续我们建立新的也就是逆转之后的关系。
如图:
循环部分:
在循环体我们要做的第一步是
r=q->next;
让r记录下余下链表
然后是
q->next=p;
建立新的关系让q的next指向p
最后是
p=q;
q=r
把q p分别赋予新的节点(这个过程也蕴含着解开原有关系的效果)继续上面的步骤。
图片来源于:https://www.2cto.com/kf/201110/106607.html。
附上我的完整测试代码:
Reverse()就是我的逆转函数了。
#include <stdio.h>
#include <stdlib.h>
typedef struct LNode
{
char data;
struct LNode *next;
}LNode,*Linklist;
int List_Create (Linklist &L,int n){
L=(Linklist)malloc(sizeof(LNode));
if(!L) return 0;
L=NULL;
Linklist p;
int i;
for(i=n;i>0;i--)
{
char ch;
scanf(" %c",&ch);
p=(Linklist)malloc(sizeof(LNode));
if(!p) return 0;
p->data=ch;
p->next=L;
L=p;
}
return 1;
}
void tranverse(Linklist L){
printf("\n\n");
Linklist p=L;
while(p){
printf("%c\n",p->data);
p=p->next;
}
}
Linklist Reverse(Linklist L){
Linklist p=L;
Linklist q=p->next;
p->next=NULL;
Linklist r;
while(q){
r=q->next;
q->next=p;
p=q;
q=r;
}
return p;
}
int main(void){
Linklist L;
List_Create(L,5);
tranverse(L);
Linklist p=Reverse(L);
tranverse(p);
}