链表反转
反转链表是面试中常见的题目,也是对链表理解的一种检验。本文将介绍两种链表反转的方法:普通方法和虚拟节点法,并使用C++进行实现。
数据结构定义
我们首先定义我们的链表结构,每个节点包含一个值和一个指向下一节点的指针。
struct NodeList{
int val;
NodeList *next;
};
我们也定义一个创建链表节点的函数CreateNodeList
,该函数接收一个整数,返回一个新的链表节点。
NodeList* CreateNodeList(int value){
auto* list = new NodeList;
list->val = value;
list->next = nullptr;
return list;
}
方法一:普通方法
普通方法是通过三个指针来实现的,分别是prev
、cur
和next
。prev
指针指向当前节点的前一个节点,cur
指向当前节点,next
保存当前节点的下一个节点。在每次循环中,我们将当前节点的next
指针指向prev
,然后将prev
和cur
向前移动一位。这样,我们就可以逆转链表的方向。代码如下:
NodeList* ReverseLink(NodeList *head){
NodeList *prev = nullptr;
NodeList *cur = head;
while (cur != nullptr){
NodeList *next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
return prev;
}
方法二:虚拟节点法
虚拟节点法则是通过创建一个虚拟的头节点,然后将每个节点插入到虚拟头节点后面。这样也能实现链表的反转。代码如下:
NodeList* ReverseLinkByVirtualNode(NodeList *head){
NodeList *virtualNode = CreateNodeList(0);
while(head != nullptr){
NodeList *next = head->next;
head->next = virtualNode->next;
virtualNode->next = head;
head = next;
}
NodeList *newHead = virtualNode->next;
delete virtualNode;
return newHead;
}
打印链表
我们创建了一个打印链表的函数PrintLink
。
void PrintLink(NodeList* list){
while(list != nullptr){
cout << list->val << " ";
list = list->next;
}
cout << endl;
}
主函数
在主函数中,我们创建了一个包含五个节点的链表,并打印出反转前和反转后的结果。
int main() {
//创建5个节点,值为1,2,3,4,5
auto* list = CreateNodeList(1);
list->next = CreateNodeList(2);
list->next->next = CreateNodeList(3);
list->next->next->next = CreateNodeList(4);
list->next->next->next->next = CreateNodeList(5);
PrintLink(list);
PrintLink(ReverseLink(CopyList(list)));
PrintLink(ReverseLinkByVirtualNode(CopyList(list)));
return 0;
}
递归法
另外,我们也可以使用递归的方法来反转链表。