反转链表有几种方法,在这先介绍一种时间复杂度为O(n)的遍历算法。
反转链表就是让所有节点的链接反向:本指向下一个节点的指针指向上一个节点。因此:
- 我们首先想到初始化一个当前指针cur指向与head指向相同的节点,cur=head;
- 然后初始化一个prev=NULL, 此时我们就想让cur所指向节点的指针指向prev;因此, cur->next=prev
- 但是当cur->next=prev时,问题出现了,我们没有办法继续访问cur指向节点的下一个节点,因为cur->next指向了prev,而不是原来指向的节点。
因此,需要再引入一个next指针。此时算法变为:
- 我们首先想到初始化一个当前指针cur指向与head指向相同的节点,cur=head; prev=NULL;
- 当cur不等于NULL的时候,一直循环遍历:
循环内容:
- 找出next; 通过next=cur->next;
- 让cur所指向节点的指针指向prev,通过cur->next=prev;
- 将prev指向cur所指向的节点,即prev前移,通过prev=cur;
- cur指针移动到下一个节点,通过cur=next;
循环完毕后,让head指向prev所指向的节点。
代码实例:
//
// main.cpp
//
//
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
//Build the node of linked list
struct node{
int data;
struct node* next;
};
struct node* newnode(int data){
//Make the pointer points to the node!
struct node* linkedlist=new struct node;
linkedlist->data=data;
linkedlist->next=NULL;
return linkedlist;
}
void print(struct node *head){
struct node *cur;
cur=head;
while (cur!=NULL) {
cout<<cur->data<<" ";
cur=cur->next;
}
cout<<endl;
}
//Reverse the linked list
void reverseLinkedlist(struct node *&head){
struct node *cur;
struct node *prev;
cur=head;
prev=NULL;
//如果我们只用cur, prev,我们首先打断cur指向节点到下一个节点的链接,让其指向prev,此时我们再想访问cur指向节点的下一个节点时我们就无法访问,因此还要引入一个next
struct node *next;
//一直遍历直到cur指向的节点为NULL
while (cur!=NULL) {
next=cur->next;
cur->next=prev;
prev=cur;
cur=next;
}
head=prev;
}
int main(){
struct node* head;
head=NULL;
struct node* cur=newnode(5);
head=cur;
cur->next=newnode(2);
cur->next->next=newnode(6);
cur->next->next->next=newnode(1);
cur->next->next->next->next=NULL;
print(head);
reverseLinkedlist(head);
print(head);
}
注意: head指针一定要通过引用传入,否则head在函数中发生变化不会对调用函数者产生影响,即无法传出。 可以这样理解:不管指向什么类型的指针,指针就起本身就是一种类型,它也有它的存储空间,即存在地址。因此我们用引用传递,其实也是为调用者的传入参数生成了一个新名字而已,其代表都是同一个地址的同一个事物;也因此操作姓名A,也就是操作姓名B。