Java 通过改变连接从单链表到双链表的转换

Java 通过改变连接从单链表到双链表的转换,java,linked-list,doubly-linked-list,Java,Linked List,Doubly Linked List,我有一个双链接列表,它模拟了单链接列表的行为。所以我有一个左,右和信息,但左总是空的。大概是这样的: 1 -> 2 -> 3 -> 4 我想要的是将它改回双重模式,而无需重新创建节点,只需解析列表并重新创建连接即可 1 -> <- 2 -><- 3 -><- 4 我的方法是: static Node toDoublyLinked(Node root) { if (root.getRight() != null) {

我有一个
双链接列表
,它模拟了
单链接列表的行为
。所以我有一个左,右和信息,但左总是空的。大概是这样的:

1 -> 2 -> 3 -> 4
我想要的是将它改回双重模式,而无需重新创建节点,只需解析列表并重新创建连接即可

1 -> <- 2 -><- 3 -><- 4
我的方法是:

static Node toDoublyLinked(Node root) {
        if (root.getRight() != null) {
            root.getRight().setLeft(root);
            return toDoublyLinked(root.getRight());
        }
        return root;
    }
这不管用。它使我的程序抛出堆栈溢出,因为当我将2连接到1时,1已经连接到2->3->4,所以它将开始一次又一次地复制列表,这不是我想要的

有什么解决办法吗

void add(int info) {
        Node s = new Node();
        if (this.info == 0) {
            this.info = info;
        } else {
            if (info < this.info) {
                if (left != null) {
                    left.add(info);
                } else {
                    s.setInfo(info);
                    this.left = s;
                }
            } else {
                if (right != null) {
                    right.add(info);
                } else {
                    s.setInfo(info);
                    this.right = s;
                }
            }
        }
    }

    public int getInfo() {
        return info;
    }

    public void setInfo(int info) {
        this.info = info;
    }

    public Node getLeft() {
        return left;
    }

    public void setLeft(Node left) {
        this.left = left;
    }

    public Node getRight() {
        return right;
    }

    public void setRight(Node right) {
        this.right = right;
    }

    @Override
    public String toString() {
        return "Node{" +
                "info=" + info +
                ", left=" + left +
                ", right=" + right +
                '}';
    }
void添加(内部信息){
节点s=新节点();
如果(this.info==0){
this.info=info;
}否则{
if(info
好的,在进一步调试之后,它似乎确实在toDoublyLinked中抛出了StackOverflow,但在toString方法中抛出了StackOverflow。为什么它还要用这个方法调用toString呢?我不是。至少不明确。我可以理解为什么toString是错误的,但是即使我对它进行了评论,它仍然不能正常工作

public static void toDoublyLinked(Node node) {
    Node current = node;
    while (current.getRight() != null) {
        current.getRight().setLeft(current);
        current = current.getRight();
    }
}
如果需要递归:

public static void toDoublyLinked(Node node) {
    if (node.getRight() != null) {
         node.getRight().setLeft(node);
         toDoublyLinked(node.getRight());
    }
}
但请记住,正如我之前所说的,由于Java没有尾部递归优化,这将在长列表上产生堆栈溢出,即使它在技术上和思想上都是正确的

如果需要递归:

public static void toDoublyLinked(Node node) {
    if (node.getRight() != null) {
         node.getRight().setLeft(node);
         toDoublyLinked(node.getRight());
    }
}

但请记住,正如我之前所说的,由于Java没有尾部递归优化,这将在长列表上产生堆栈溢出,即使它在技术上和思想上都是正确的

不应使用会导致长列表上堆栈溢出的递归。 您应该改为使用迭代方法,例如:

public static void toDoublyLinked(Node node){
    Node currentNode = node ;
    while(currentNode.getRight() !=null){
         currentNode.getRight().setLeft(currentNode);
         currentNode = currentNode.getRight();
    }
}
这样,无论列表的长度如何,代码都不会导致堆栈溢出。当然,您有一个额外的变量,但您将避免长列表的堆栈溢出,并提高复杂性(调用函数的成本更高)

但是,如果您仍然只想使用递归(即使不应该),下面是一段代码:

public static void toDoublyLinked(Node node) {
    if (node.getRight() != null) {
         node.getRight().setLeft(node);
         toDoublyLinked(node.getRight());
    }
}

您不应该使用会导致长列表上堆栈溢出的递归。 您应该改为使用迭代方法,例如:

public static void toDoublyLinked(Node node){
    Node currentNode = node ;
    while(currentNode.getRight() !=null){
         currentNode.getRight().setLeft(currentNode);
         currentNode = currentNode.getRight();
    }
}
这样,无论列表的长度如何,代码都不会导致堆栈溢出。当然,您有一个额外的变量,但您将避免长列表的堆栈溢出,并提高复杂性(调用函数的成本更高)

但是,如果您仍然只想使用递归(即使不应该),下面是一段代码:

public static void toDoublyLinked(Node node) {
    if (node.getRight() != null) {
         node.getRight().setLeft(node);
         toDoublyLinked(node.getRight());
    }
}


我觉得你这里的东西看起来不错。但是,我们需要setLeft()和getRight()代码来帮助您。我不理解toDoublyLinked()中第一次返回的含义。如果在“真实”根上调用该方法。。。该方法最终不会返回最右边的节点吗?这样做的意义是什么?这里的一个问题是使用一个方法而不是一个过程,即您将列表中最左边的节点作为参数,但返回(修改后)最右边的节点。此外,Java没有尾部递归优化,因此您的代码将在相当长的列表上堆栈溢出。改用迭代。好的。我想再次返回leftMostNode。我认为通过递归的方式,不知何故。。。这会给我正确的结果。你说的很有道理。那么我怎样才能改变我的方法,让它做它应该做的事情,并返回最左边的节点呢?我想你这里看到的看起来是正确的。但是,我们需要setLeft()和getRight()代码来帮助您。我不理解toDoublyLinked()中第一次返回的含义。如果在“真实”根上调用该方法。。。该方法最终不会返回最右边的节点吗?这样做的意义是什么?这里的一个问题是使用一个方法而不是一个过程,即您将列表中最左边的节点作为参数,但返回(修改后)最右边的节点。此外,Java没有尾部递归优化,因此您的代码将在相当长的列表上堆栈溢出。改用迭代。好的。我想再次返回leftMostNode。我认为通过递归的方式,不知何故。。。这会给我正确的结果。你说的很有道理。那么我怎样才能改变我的方法,让它做它应该做的,并返回最左边的节点呢?好的,我应该提到。我不想使用任何附加变量。这就是为什么我尝试递归,只返回最终解决的Listeded,以包含完整性的答案(以及为什么在Java中这是一个坏主意的注释)@PiotrWilkin oops认为我的答案中不需要额外的变量。因此,这应该是公认的答案+由于java不是按引用传递而是按引用的副本传递,ToDoublyLink对节点所做的任何事情都会对我的ini产生影响吗