链表的JAVA实现
在JAVA中,JAVA的集合(collection)实现了各种常用的数据结构,包括链表。
下面自己来实现简单的单链表。链表是由一个个的相互连接的结点组成,结点又由数据域和指针域组成,指针域指向下一个结点。
1 2 3
| ┌───┬───┐ ┌───┬───┐ ┌───┬───┐ ┌───┬───┐ │ A │ ●─┼──>│ B │ ●─┼──>│ C │ ●─┼──>│ D │ │ └───┴───┘ └───┴───┘ └───┴───┘ └───┴───┘
|
JAVA没有struct结构体,所以用一个Node Class表示结点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public class ListNode<E>{ private E data; private ListNode<E> next = null; public ListNode(E data) { this.data = data; } public ListNode(E data, ListNode<E> next) { this.data = data; this.next=next; } public void setData(E data) { this.data = data; } public E getData() { return this.data; } public void setNext(ListNode<E> next) { this.next = next; } public ListNode<E> getNext() { return this.next; } }
|
链表反转
面试题5 - 从尾到头打印链表并不算是真正的链表反转,它只是将链表中的元素放进到新的数组对象中去了。
对于链表的反转问题,可以新建链表及节点关系;也可以在原有列表的基础上进行指针的变换,这样考察点就在于指针的运用(pointer manipulation)。这里主要阐述在原有列表的基础上进行指针的变换的方法。
迭代法(Iterative)
迭代法是从前向后顺序地交换两个节点的相对位置。
我们需要三个指针:
- pre pointer:存储上一个节点,因为是单链表,在迭代过程中,当链表头移动到下一个结点后,就无法访问上一个结点了。
- cur pointer:指示我们当前的指向。
- next pointer:当我们改变当前结点指向后,我们就会丢失原来的下一个结点,所以需要一个结点来储存,才能知道我们的下一次迭代的前进方向。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public static ListNode<Integer> LinkedListReverse1(ListNode<Integer> listNode) { if (listNode == null) { return listNode; } ListNode<Integer> pre = null; ListNode<Integer> cur = listNode; ListNode<Integer> next = new ListNode<>(null); while (cur != null) { next = cur.getNext(); cur.setNext(pre); pre = cur; cur = next; } return pre; }
|
Time: O(n)
Space: O(1)
递归法(Recursive)
递归法是从后向前逆序地交换两c个节点的相对位置。递归即是借助了系统的”栈”。
每一次迭代就像是向另一个人发出了命令:将我(本节点,本此迭代的head)后面的所有结点反转,不包括我。
每一次迭代,我们有的资源是返回的反转后的剩下链表(rlh,reversed list head)以及本节点(head);每一次迭代,执行的动作是,将rlh指向我自己,再将新的rlh返回到上一次迭代。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public static ListNode<Integer> LinkedListReverse2(ListNode<Integer> listNode) { if (listNode == null || listNode.getNext() == null) { return listNode; } ListNode<Integer> reHead = LinkedListReverse2(listNode.getNext()); listNode.getNext().setNext(listNode); listNode.setNext(null); return reHead; }
|
Time: O(n)
Space: O(n)
代码
ListNode.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| public class Main { public static void main(String[] args) { ListNode<Integer> node0 = new ListNode<>(0); ListNode<Integer> node1 = new ListNode<>(1); ListNode<Integer> node2 = new ListNode<>(2); ListNode<Integer> node3 = new ListNode<>(3); node0.setNext(node1); node1.setNext(node2); node2.setNext(node3); ListNode<Integer> h1 = node0; System.out.println("反转前的链表:"); while (h1 != null) { System.out.println(h1.getData()); h1 = h1.getNext(); } node0 = LinkedListReverse1(node0);
ListNode<Integer> h2 = node0; System.out.println("反转后的链表:"); while (h2 != null) { System.out.println(h2.getData()); h2 = h2.getNext(); } } public static ListNode<Integer> LinkedListReverse1(ListNode<Integer> listNode) { if (listNode == null) { return listNode; } ListNode<Integer> pre = null; ListNode<Integer> cur = listNode; ListNode<Integer> next = new ListNode<>(null); while (cur != null) { next = cur.getNext(); cur.setNext(pre); pre = cur; cur = next; } return pre; }
public static ListNode<Integer> LinkedListReverse2(ListNode<Integer> listNode) { if (listNode == null || listNode.getNext() == null) { return listNode; } ListNode<Integer> reHead = LinkedListReverse2(listNode.getNext()); listNode.getNext().setNext(listNode); listNode.setNext(null); return reHead; }
}
|
Main.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| public class Main { public static void main(String[] args) { ListNode<Integer> node0 = new ListNode<>(0); ListNode<Integer> node1 = new ListNode<>(1); ListNode<Integer> node2 = new ListNode<>(2); ListNode<Integer> node3 = new ListNode<>(3); node0.setNext(node1); node1.setNext(node2); node2.setNext(node3); ListNode<Integer> h1 = node0; System.out.println("反转前的链表:"); while (h1 != null) { System.out.println(h1.getData()); h1 = h1.getNext(); } node0 = LinkedListReverse1(node0);
ListNode<Integer> h2 = node0; System.out.println("反转后的链表:"); while (h2 != null) { System.out.println(h2.getData()); h2 = h2.getNext(); } } public static ListNode<Integer> LinkedListReverse1(ListNode<Integer> listNode) { if (listNode == null) { return listNode; } ListNode<Integer> pre = null; ListNode<Integer> cur = listNode; ListNode<Integer> next = new ListNode<>(null); while (cur != null) { next = cur.getNext(); cur.setNext(pre); pre = cur; cur = next; } return pre; }
public static ListNode<Integer> LinkedListReverse2(ListNode<Integer> listNode) { if (listNode == null || listNode.getNext() == null) { return listNode; } ListNode<Integer> reHead = LinkedListReverse2(listNode.getNext()); listNode.getNext().setNext(listNode); listNode.setNext(null); return reHead; }
}
|
References
一篇文章搞定面试中的链表题目(java实现)
Java单链表反转 详细过程
【LeetCode算法题详解】链表反转(已添加字幕)