链表倒置是一个经常遇到的问题,下面将用图示的方式讲述链表倒置的过程。
假设链表的长度为4,头指针head指向第一个节点。另外还有两个非常重要的指针,prev:带领head指针往下走,是个领航员,worker:位于head之后,为指针变换服务。最后返回的结果是一个head指针,指向的是一个已经倒置的链表。
1. 初始化:
Node *prev = null;
Node *worker = null;
2. 开始工作
prev = head.next;
worker = head;
3. 准备第一次指针变换
head = prev;
prev = head.next;
4. 变换指针
head.next = worker;
worker.next = null;
5. 准备第二次变换
worker = head;
head = prev;
prev = head.next;
6. 第二次指针变换
head.next = worker;
7. 准备第三次变换
worker = head;
head = prev;
8. 第三次变换
head.next = worker;
至此,已经变换完成。在一步步的代码中发现了一丝重复了吗?
让我们把之前每一步的代码都合在一起:
Node *prev = null;
Node *worker = null;
prev = head.next;
worker = head;
head = prev;
prev = head.next;
head.next = worker;
worker.next = null;
worker = head;
head = prev;
prev = head.next;
head.next = worker;
worker = head;
head = prev;
head.next = worker;
试着在第三行,第八行,第十二行之后,加一个空行。像这样:
Node *prev = null;
Node *worker = null;
prev = head.next;
worker = head;
head = prev;
prev = head.next;
head.next = worker;
worker.next = null;
worker = head;
head = prev;
prev = head.next;
head.next = worker;
worker = head;
head = prev;
head.next = worker;
现在我们将第一个节点的next域置为空的操作换种说法,也即是,在第四行上加上head.next = null,并删除第9行中的work.next=null,效果都是将第一个节点的next置为null; 之后,将最后一次的过程也改一下,在倒数第二行加上一句 prev = head.next;因为此时head已经指向最后一个节点,head.next = null, 也即 prev = null;
改造之后的代码为:
Node *prev = null;
Node *worker = null;
prev = head.next;
head.next = null;
worker = head;
head = prev;
prev = head.next;
head.next = worker;
worker = head;
head = prev;
prev = head.next;
head.next = worker;
worker = head;
head = prev;
prev = head.next;
head.next = worker;
嗯,现在非常清晰了。在加上判断条件吧,就以最后一次的操作为截至,此时,三个指针的值为:
prev = null
head = 最后一个节点
worker = 倒数第二个节点
最后以 prev是否为null判断是否到达尾节点就可以了。
让我们来组装一下代码吧:
Node* ReverseList(Node *head) {
Node *prev = null;
Node *worker = null;
if(head == null) {
return null;
}
if(head.next == null) {
return head;
}
prev = head.next;
head.next = null;
while(prev != null) {
worker = head;
head = prev;
prev = head.next;
head.next = worker;
}
return head;
}
大功告成!