Java API中的鏈表是雙向的,我們這裏自己新建一個類代表我們的鏈表元素結點:
class Node {
int value;
Node next;
public Node(int i) {
setValue(i);
}
public Node() {
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
然後我們拼接一根鏈表:
Node linkedList = new Node();
linkedList.setValue(1);
Node current = linkedList;
for (int i = 2; i < 10; i++) {
Node tNode = new Node(i);
current.setNext(tNode);
current = tNode;
}
這跟鏈表有9個元素,從1一直指向9.
第一種方法需要兩個額外的結點空間,通過循環不停的反向相鄰結點並記錄後續的位置:
private Node reverse(Node head) {
Node temp = head.getNext();
Node flag = temp.getNext();
head.setNext(null);
while (flag != null) {
temp.setNext(head);
head = temp;
temp = flag;
flag = flag.getNext();
}
temp.next = head;
return temp;
}
把鏈表頭結點傳入即可實現反轉並返回新的頭結點。
我努力嘗試了使用一個額外結點實現反轉,沒能成功:
private Node reverse(Node head) {
Node temp = head.getNext();
while (temp.getNext() != null) {
head.getNext().setNext(head);
head = temp;
temp = temp.next;
}
temp.next = head;
return temp;
}
如果各位有隻使用一個額外空間就能反轉的請留言指點,謝謝。
第二種反轉方法是使用迭代,需要傳入鏈表的前兩個元素:
private Node reverseRecur(Node head, Node next) {
if (next == null) {
return head;
}
if (head.getNext().equals(next)) {//第一次進來
head.setNext(null);
}
if (next.getNext() != null) {
Node next2 = next.getNext();
next.setNext(head);
return reverseRecur2(next, next2);
}
next.setNext(head);
return next;
}
我努力嘗試只傳入頭結點來反轉,但是總是不成功:
private Node reverseRecur(Node head) {
Node tail = head.getNext();
if (tail.getNext() != null) {
Node flag = reverseRecur(tail);
flag.setNext(head);
head.setNext(null);
return head;
}
tail.setNext(head);
head.setNext(null);
return head;
}
我將鏈表長度設置爲10000進行對比,循環的時間和空間都比迭代更好。
爲什麼迭代更常用呢?