以下关于单向链表翻转问题,来自博主Little_T.
这次介绍经常在面试中被问到的单向链表的反转问题,问题的解决方法有多种
- 最普通的是从头到尾扫描链表,然后对链表进行反转。
- 使用单个参数的递归方法;使用单个参数是相当于不断的往链表后部深入,并且在每次深入的递归中保存了下一个节点和当前节点的信息,再调用递归后处理当前节点和下一个节点的关系;其中比较有特点的处理过程是返回值的处理,每次递归后返回的指针为同一个;
- 使用两个参数的递归方法,外加一个当前链表头节点的前一个结点的指针,在进一步递归之前处理好头节点和其前一个节点的关系。
#include <iostream>
#include <string>
using namespace std;
struct Node{
int value;
Node* next;
};
//使用非递归的链表反转方法
Node* ReverseList1(Node *Ptr)
{
Node *pre = NULL;
Node *Current = Ptr;
Node *pnext = NULL;
while ( Current != NULL){
pnext = Current->next;
Current->next = pre;
pre = Current;
Current = pnext;
}
return pre;
}
// 一个参数的递归反转方法
// 将当前节点的下一个节点保存好,并将当前节点从链表中取出,再递归处理以后的链表
// 同时reverseRest没有改变,一直保存了链表的最后一个节点的指针
Node* ReverseList2(Node *ptr){
if (ptr->next == NULL)
return ptr;
Node *nextNode = ptr-> next;
ptr->next = NULL;
Node *reverseRest = ReverseList2(nextNode);
nextNode->next = ptr;
return reverseRest;
}
// 递归实现2:两个参数的递归调用方法
// 传递一个当前链表头节点的前一个节点的指针,在函数中将当前头节点的next改为其前一个节点,并递归调用
Node* ReverseList3(Node *ptr, Node *pre){
if (ptr->next == NULL){
ptr->next = pre;
return ptr;
}
else{
Node *next = ptr->next;
ptr->next = pre;
ReverseList3(next, ptr);
}
}
void printList(Node *Ptr){
Node * Current = Ptr;
while (Current != NULL){
cout << Current->value << " ";
Current = Current->next;
}
cout << endl;
}
int main(){
Node *head = NULL;
for (int i = 9; i > 0; i--){
Node *p = new Node;
p->next = head;
p->value = i;
head = p;
}
cout << "The Lsit:" << endl;
printList(head);
head = ReverseList1(head);
cout << "After reverseList1():" << endl;
printList(head);
head = ReverseList2(head);
cout << "After reverseList2():" << endl;
printList(head);
Node * tmp = NULL;
head = ReverseList3(head, tmp);
cout << "After reverseList3():" << endl;
printList(head);
return 1;
}
以上基本上就是翻转问题的模板了,什么区间翻转只需要改变起始头结点即可。
相望能够帮助大家!