前言:单链表是数据结构中非常常用的一种线性表,有很多的用法,那么我们怎样将一个单链表进行逆转呢?这也是我初学的是时候所遇到的问题之一,那么今天来跟大家分享下我总结的方法。
单链表逆转
链表的逆转,又可以成为翻转或逆置链表,表达的是同一个意思,以图1所示链表为例:
图1 未逆转的链表
经过逆转后得到的新链表如图2:
图2 逆转后的链表
通过比较图1、2可知所谓的链表逆转,其实就是将链表整体反过来,即头变成尾,为变成头,那么如何实现呢?
我们将此功能定义成一个函数,用来接收原链表的地址,然后返回逆转后链表的首地址。
函数接口定义:
LNode *Reverse( LNode *head );
链表的定义:
typedef struct LNode{
int data;
struct LNode *next
}LNode;
具体操作:
- 使用3个指针,逐个节点的逆转。
- p q两个指针分别指向想要逆转关系的两个节点。
- p指向前一个节点,q指向后一个节点。
- r指向q后余下的链表。
这里我们忽略头结点,也就是连头结点一起逆转。
进行初始化:
p=head;
q=p->next;
p->next=NULL;
这里我们先让p指向第一个节点,q指向第二个节点。然后解开他们之间的关系
让第一个的节点的next指向NULL,以便后续我们建立新的也就是逆转之后的关系。
如图:
循环部分:
在循环体我们要做的第一步是
r=q->next;
让r记录下余下链表
然后是
q->next=p;
建立新的关系让q的next指向p
最后是
p=q;
q=r
把q p分别赋予新的节点(这个过程也蕴含着解开原有关系的效果)继续上面的步骤。 下面附上我的完整代码:
#include<iostream>
#include<cstdlib>
using namespace std;
typedef struct LNode{ //链表定义
int data;
struct LNode *next;
}LNode;
//链表逆转函数
LNode *Reverse(LNode *head)
{
LNode *p,*q,*r;
p=head;
q=p->next;
p->next=NULL;
while(q)
{
r=q->next;
q->next=p;
p=q;
q=r;
}
return p; //返回逆转后的链表首地址
}
//创建链表
LNode *initList()
{
int n;cin>>n; //定义创建的节点数
LNode *head,*node,*end; //定义头节点,普通节点,尾节点
head = (LNode *)malloc(sizeof(LNode)); //给头节点申请内存
cin>>head->data; //给头结点赋值
end = head; //若是空表,则头尾地址一致
for(int i=0;i<n-1;i++){ //利用for循环向链表中添加数据
node = (LNode *)malloc(sizeof(LNode)); //给普通节点申请内存空间
cin>>node->data; //给数据域赋值
end->next = node; //让上一个节点的数据域指向当前节点
end = node; //end指向当前节点,最终end指向尾节点
}
end->next = NULL; //给end的指针域置空
return head;
}
//打印链表
void printf(LNode *head)
{
LNode *p = head;
while(p != NULL){ //遍历链表并打印
cout<<p->data<<" ";
p = p->next;
}
cout<<endl;
}
int main()
{
LNode *myLNode=NULL; //创建头节点
myLNode=initList(); //创建链表
cout<<endl;
printf(myLNode); //打印逆转前的链表
myLNode=Reverse(myLNode); //将链表进行逆转
printf(myLNode); //打印逆转后的链表
return 0;
}
输入输出如下: