链表的反转是老生常谈的一个问题了,同时也是面试中常考的一道题。最简单的一种方式就是使用栈,因为栈是先进后出的。实现原理就是把链表节点一个个入栈,当全部入栈完之后再一个个出栈,出栈的时候在把出栈的结点串成一个新的链表。 原理如下
#include<iostream>
#include<stack>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
class Solution {
public:
ListNode* reverseList(ListNode* head)
{
stack<ListNode*> s;
//将链表节点一个个都放入栈中
while (head != NULL)
{
s.push(head);
head=head->next;
}
//判断栈是否为空
if (s.empty())
{
return NULL;
}
//放入栈中后,再挨个取出
//取出栈中第一个节点,作为逆置链表的头节点
ListNode* first = s.top();
s.pop();
//临时指针把节点连接起来
ListNode* temp = first;
//栈中元素挨个弹出
while (!s.empty())
{
temp->next = s.top();
s.pop();
temp = temp->next;
}
//注意要把之前链表的头节点的next指针指向NULL,否则会构成环
temp->next = NULL;
return first;//返回逆置链表头节点
}
};
//测试-----------------
void input(ListNode* l)
{
int num;
cin >> num;
if (num == -1)
return;
l->val = num;
ListNode* end = l;
while (1)
{
cin >> num;
if (num == -1)
return;
ListNode* newNode = new ListNode(num);
end->next=newNode;
end = newNode;
}
}
void display(ListNode* l)
{
if (l == NULL)
{
return;
}
while (l!=NULL)
{
cout << l->val;
l = l->next;
}
}
void test()
{
ListNode* l = new ListNode(0);
input(l);
Solution s;
l = s.reverseList(l);
cout << "链表打印:" << endl;
display(l);
cout << endl;
}
int main()
{
test();
system("pause");
return 0;
}
双链表求解是把原链表的结点一个个摘掉,每次摘掉的链表都让他成为新的链表的头结点,然后更新新链表。下面以链表1→2→3→4为例画个图来看下。
class Solution {
public:
ListNode* reverseList(ListNode* head)
{
//新链表---头插法完成链表逆置
ListNode* newList=NULL;
while (head)
{
//保存下一个节点
ListNode* nextNode = head->next;
//每次访问原链表的节点,该节点都会成为新链表的头结点
head->next = newList;
//更新新链表头节点位置
newList = head;
//head指向原链表当前遍历到的节点
head = nextNode;
}
return newList;
}
};
class Solution {
public:
ListNode* reverseList(ListNode* head)
{
//递归退出条件:当前节点为空,返回到上一个节点的位置
if (head->next == NULL)
return head;//当最后一次递归到尾节点的时候,发现最后一个节点的next为NULL,因此返回最后一个节点赋值给ret,因此ret最后得到的就是尾节点
//通过不断的递归,找到倒数第二个节点
ListNode* ret=reverseList(head->next);//ret指针接收的是没有逆置前,链表中最后一个节点
//下面是递归完后,进行回溯的操作
head->next->next = head;
head->next = NULL;
return ret;
}
};
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* cur = NULL, *pre = head;
while (pre != NULL) {
ListNode* t = pre->next;
pre->next = cur;
cur = pre;
pre = t;
}
return cur;
}
};
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (head == NULL) { return NULL; }
ListNode* cur = head;
while (head->next != NULL) {
ListNode* t = head->next->next;
head->next->next = cur;
cur = head->next;
head->next = t;
}
return cur;
}
};