最近有人聊到单向链表反转的相关问题,自己闲来无事研究一下。
先画图了解一下单向链表
看一下,一个链表有多个节点组成,每个节点指向下一个节点,最后一个的指向是null。
思路:从头节点开始设置头节的nextNode为null,当前节点的nextNode指向头节点,如此一来还需要定义一个nextNode来记录下一个节点,然后指针统一向右移动一位。三个重要角色:firstNode、currentNode、nextNode。
STEP 1
设置first节的nextNode为null
STEP 2
current节点的下一个节点指向first节点
STEP 3
让current节点的下一个节点指向first节点,并让“指针”右移一位。
current.setNextNode(firstNode);
first = current;
current = next;
next = next.getNextNode();
STEP 4
以此类推,直到current的下一个节点为空(这里后面会看到)
如果while条件为 (current.getNextNode != null),此时会看到current和first是断开的,所以需要:
current.setNextNode(firstNode);
最后返回current。
有了思路上代码
准备一个链表节点
public class Node {
private int date;
private Node nextNode;
public int getDate() {
return date;
}
public void setDate(int date) {
this.date = date;
}
public Node getNextNode() {
return nextNode;
}
public void setNextNode(Node nextNode) {
this.nextNode = nextNode;
}
}
构造一个链表
Node head = new Node();
Node node1 = new Node();
Node node2 = new Node();
Node node3 = new Node();
Node node4 = new Node();
Node tail = new Node();
head.setDate(1);
head.setNextNode(node1);
node1.setDate(2);
node1.setNextNode(node2);
node2.setDate(3);
node2.setNextNode(node3);
node3.setDate(4);
node3.setNextNode(node4);
node4.setDate(5);
node4.setNextNode(tail);
tail.setDate(6);
tail.setNextNode(null);
遍历链表
Node temp = head;
while (temp != null){
System.out.print(temp.getDate() + " -> ");
temp = temp.getNextNode();
}
反转链表
public static Node revert(Node head){
// 惯性的校验参数
if (head == null || head.getNextNode() == null) {
return head;
}
// 定义三个重要角色
Node firstNode = head; // 记录头节点的位置
Node current = head.getNextNode();// 记录当前节点的位置
Node next = current.getNextNode();// 记录下一个节点的位置
// 设置头节点指向null
firstNode.setNextNode(null);
// 结束条件为当前节点的下一个节点不为null
while (current.getNextNode() != null){
// 设置当前节点的下一个节点为firstNode
current.setNextNode(firstNode);
// “指针”右移一位
firstNode = current;
current = next;
next = next.getNextNode();
}
// 现在当前节点的下一个节点还是指向null的,所以设置
current.setNextNode(firstNode);
return current;
}
完整代码
public class ConvertNodeTest {
public static void main(String[] args) {
Node head = new Node();
Node node1 = new Node();
Node node2 = new Node();
Node node3 = new Node();
Node node4 = new Node();
Node tail = new Node();
head.setDate(90);
head.setNextNode(node1);
node1.setDate(63);
node1.setNextNode(node2);
node2.setDate(984);
node2.setNextNode(node3);
node3.setDate(35);
node3.setNextNode(node4);
node4.setDate(76);
node4.setNextNode(tail);
tail.setDate(53);
tail.setNextNode(null);
// 反转前遍历
Node temp = head;
while (temp != null){
System.out.print(temp.getDate() + " -> ");
temp = temp.getNextNode();
}
System.out.println();
// 反转后遍历
Node revert = revert(head);
Node temp2 = revert;
while (temp2 != null){
System.out.print(temp2.getDate() + " -> ");
temp2 = temp2.getNextNode();
}
}
public static Node revert(Node head){
// 惯性的校验参数
if (head == null || head.getNextNode() == null) {
return head;
}
// 定义三个重要角色
Node firstNode = head; // 记录头节点的位置
Node current = head.getNextNode();// 记录当前节点的位置
Node next = current.getNextNode();// 记录下一个节点的位置
// 设置头节点指向null
firstNode.setNextNode(null);
// 结束条件为当前节点的下一个节点不为null
while (current.getNextNode() != null){
// 设置当前节点的下一个节点为firstNode
current.setNextNode(firstNode);
// “指针”右移一位
firstNode = current;
current = next;
next = next.getNextNode();
}
// 现在当前节点的下一个节点还是指向null的,所以设置
current.setNextNode(firstNode);
return current;
}
}
输出结果
90 -> 63 -> 984 -> 35 -> 76 -> 53 ->
53 -> 76 -> 35 -> 984 -> 63 -> 90 ->
时间复杂度
O(n)