通过更改连接从单链表转换为双链表
Transforming from singly linked list to doubly by changing the connections
我有一个 doubly linked list
可以模拟 singly linked list
的行为。所以我有左、右和信息,但左边始终为空。像这样:
1 -> 2 -> 3 -> 4
我想要的是在不重新创建节点的情况下将其改回 doubly,只需解析列表并重新建立连接。
1 -> <- 2 -><- 3 -><- 4
我有
class Node {
private int info;
private Node left;
private Node right;
还有我的方法:
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 +
'}';
}
好的,经过更多调试,它似乎确实在 toDoublyLinked 中抛出了 Whosebug,但在 toString 方法中。为什么它甚至在该方法中调用 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){
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());
}
}
我有一个 doubly linked list
可以模拟 singly linked list
的行为。所以我有左、右和信息,但左边始终为空。像这样:
1 -> 2 -> 3 -> 4
我想要的是在不重新创建节点的情况下将其改回 doubly,只需解析列表并重新建立连接。
1 -> <- 2 -><- 3 -><- 4
我有
class Node {
private int info;
private Node left;
private Node right;
还有我的方法:
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 +
'}';
}
好的,经过更多调试,它似乎确实在 toDoublyLinked 中抛出了 Whosebug,但在 toString 方法中。为什么它甚至在该方法中调用 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){
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());
}
}