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产生影响吗