Java 编译器不会在单链表的递归反转中前进

Java 编译器不会在单链表的递归反转中前进,java,recursion,singly-linked-list,Java,Recursion,Singly Linked List,我在SingleLinkedList类中有一个递归静态方法,该类由于一个不确定的原因而永远运行。此类是泛型的,其声明如下所示: public class SinglyLinkedList<E>{ private static class Node<E> { private E element; private Node<E> next; public Node(E e, Node<E> n) { this

我在SingleLinkedList类中有一个递归静态方法,该类由于一个不确定的原因而永远运行。此类是泛型的,其声明如下所示:

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> 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;
    }
此外,SinglyLinkedList类具有以下字段:

private Node<E> head = null;

private Node<E> tail = null;

private int size = 0;
反向方法使用名为removeFirstNode的非静态方法,其目的是删除单链表中的第一个节点并返回它:

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;
}
问题是,当我尝试在大小等于2的SingleLinkedList上运行reverse方法时,编译器会到达该行

reversed.addLast(first);
reversed.addLast(first);
然后在addLast方法中,它停在行上

this.tail = n;
this.tail = n;
永远不停地奔跑。如果大小等于3或更多,编译器将到达该行

reversed.addLast(first);
reversed.addLast(first);
并在那里停止,甚至没有输入addLast方法。现在,如果我更换线路

Node<E> answer = this.head;
编辑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实现更改为以下内容:

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> 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打印列表,我想它会遍历列表,并且由于循环而从未完成。

请提供可以生成和调试的完整代码。看看这个主意。此外,您可能希望熟悉调试器,这种短代码可以逐行运行,然后您将看到发生了什么以及如何进行。您如何知道JVM在某一行上“莫名其妙地终止”?你是在使用调试器还是什么?是的,我正在使用调试器。我相信这就是问题所在,因此我提出了注释掉的解决方案,但我仍然想知道:这不是循环链接列表背后的概念吗?如果是这样,为什么会导致问题?啊,toString方法中的while循环导致了问题。就这样!