[英]compiler won't advance in recursive reversal of singly linked list
我在SinglyLinkedList
類中有一個遞歸靜態方法,由於不確定的原因,該方法永遠運行。 此類是通用的,其聲明如下所示:
public class SinglyLinkedList<E>{
該類具有一個內部通用類Node
,它看起來像這樣:
private static class Node<E> {
private E element;
private Node<E> next;
public Node(E e, Node<E> n) {
this.element = e;
this.next = n;
}
public E getElement() {
return this.element;
}
public Node<E> getNext() {
return this.next;
}
public void setNext(Node<E> n) {
this.next = n;
}
}
此外, SinglyLinkedList
類具有以下字段:
private Node<E> head = null;
private Node<E> tail = null;
private int size = 0;
我遇到麻煩的方法稱為reverse
,其目的是以遞歸的方式反向單鏈表的順序。 這是此方法的代碼:
public static SinglyLinkedList reverse(SinglyLinkedList l) {
if (l.size < 2) return l;
Node first = l.removeFirstNode();
SinglyLinkedList reversed = reverse(l);
reversed.addLast(first);
return reversed;
}
reverse
方法使用一種稱為removeFirstNode
的非靜態方法,其目的是刪除單鏈列表中的第一個Node
並返回它:
private Node<E> removeFirstNode() {
if (isEmpty()) return null;
//Node<E> answer = new Node<>(this.head.getElement(), null);
Node<E> answer = this.head;
this.head = this.head.getNext();
this.size--;
if (this.size == 0) this.tail = null;
return answer;
}
reverse
方法還使用稱為addLast
的非靜態方法,其目的是將給定的Node
添加到單鏈表的末尾:
private void addLast(Node<E> n) {
if (isEmpty()) this.head = n;
else this.tail.setNext(n);
this.tail = n;
this.size++;
}
問題是,當我嘗試在size
等於2的SinglyLinkedList
上運行reverse
方法時,編譯器進入該行
reversed.addLast(first);
然后在addLast
方法中,它在行上停止
this.tail = n;
並且永遠運行而不會終止。 如果size
等於或大於3,則編譯器進入該行
reversed.addLast(first);
甚至不輸入addLast
方法就停在那里。 現在如果我更換線
Node<E> answer = this.head;
與當前已注釋掉的行
Node<E> answer = new Node<>(this.head.getElement(), null);
reverse
方法將終止,沒有任何問題。 誰能解釋這是怎么回事?
編輯:我剛剛意識到size
3或更大的不同行為僅僅是遞歸的產物。 真正的問題在於size
等於2且方法莫名其妙地在行終止的情況
this.tail = n;
編輯2:
最小代碼:
public class SinglyLinkedList<E>{
private static class Node<E> {
private E element;
private Node<E> next;
public Node(E e, Node<E> n) {
this.element = e;
this.next = n;
}
public E getElement() {
return this.element;
}
public Node<E> getNext() {
return this.next;
}
public void setNext(Node<E> n) {
this.next = n;
}
}
private Node<E> head = null;
private Node<E> tail = null;
private int size = 0;
public SinglyLinkedList() {}
public int size() { return this.size; }
public boolean isEmpty() {
return this.size == 0;
}
public void addLast(E e) {
Node<E> newest = new Node<>(e, null);
if (isEmpty())
this.head = newest;
else
this.tail.setNext(newest);
this.tail = newest;
this.size++;
}
@Override
public String toString() {
String output = "";
if (this.size > 0) {
Node<E> current_node = head;
while (current_node != null) {
output += current_node.getElement();
if (current_node != tail) output += ", ";
else output += "\n";
current_node = current_node.getNext();
}
}
return output;
}
private void addLast(Node<E> n) {
if (isEmpty()) this.head = n;
else this.tail.setNext(n);
this.tail = n;
this.size++;
}
private Node<E> removeFirstNode() {
if (isEmpty()) return null;
//Node<E> answer = new Node<>(this.head.getElement(), null);
Node<E> answer = this.head;
this.head = this.head.getNext();
this.size--;
if (this.size == 0) this.tail = null;
return answer;
}
public static SinglyLinkedList reverse(SinglyLinkedList l) {
if (l.size < 2) return l;
Node first = l.removeFirstNode();
SinglyLinkedList reversed = reverse(l);
reversed.addLast(first);
return reversed;
}}
測試類別:
public static void main(String[] args) {
int n = 4;
SinglyLinkedList<Integer> list = new SinglyLinkedList<>();
for (int i = 1; i <= n; i++) list.addLast(i);
System.out.print(list);
System.out.print(SinglyLinkedList.reverse(list));
}
removeFirstNode()
實現不會取消鏈接該節點的下一個指針。
在原始鏈表中,第一個節點的下一個點指向第二個節點,第二個節點的下一個指針為null。
在新列表中,第一個節點的下一個指針將指向第二個節點,但是第二個節點的下一個指針將指向第一個節點(以前是第二個節點)。
這樣的東西(原始列表):
+---+ +---+
| A |--->| B |--->null
+---+ +---+
由於A的下一個指針仍然指向B,因此重新排序成為了這種情況:
+---+ +---+
| B |--->| A |---+
+---+ +---+ |
^ |
| |
+--------------+
您可以將removeFirstNode()
實現更改為以下形式:
private Node<E> removeFirstNode() {
if (isEmpty()) return null;
Node<E> answer = this.head;
this.head = this.head.getNext();
answer.next = null; // Set next ptr to null
this.size--;
if (this.size == 0) {
this.tail = null;
}
return answer;
}
該代碼可能看起來像“停止”,因為調試器嘗試使用toString()
來打印出列表,我想它會遍歷列表並且由於循環而無法完成。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.