我有一个链接列表,我正在尝试创建另一个链接列表的副本,这个副本是一个深层副本,因为元素类型是char。由于链表的复杂性,我试图不使用add方法。我的代码如下所示。此外,我想以递归方式将某些列表中的所有元素添加到我的原始列表中,但我的实现问题是它只添加列表中的第一个元素而不是所有元素。为什么会这样?
public class CharLinkedList {
private static class Node {
private char info;
private Node next;
public Node(char d) {
this.data = d;
this.next = null;
}
}
private int size;
private Node head;
public CharLinkedList() {
this.size = 0;
this.head = null;
}
public CharLinkedList(CharLinkedList some) {
this.size = some.size;
Node node = some.head;
this.head = new Node(other.head.info);
if(node.next != null)
{
this.head.next = new Node(node.next.info);
node = node.next;
this.head.next.next = new Node(node.next.info);
}
}
public void addAll(CharLinkedList some) {
if(some == null){
return;
}
if (this.size == 0) {
Node someNode = new Node(some.get(0));
this.head = someNode;
}
else {
CharLinkedList.addAll(some, this.head.next);
}
this.size++;
}
private static void addAll(CharLinkedList some, Node node) {
if(node.next == null)
{
Node someNode = new Node(some.get(0));
node.next = someNode;
}
else {
CharLinkedList.addAll(some, node.next);
}
}
public static void main(String[] args) {
CharLinkedList l = new CharLinkedList();
l.add('z');
l.add('o');
l.add('m');
CharLinkedList some = new CharLinkedList(l);
some.add('b');
some.add('i');
some.add('e');
System.out.println(l);
System.out.println(some);
// now i change the state of l and append all of some
l.set(1, 'p');
l.addAll(some);
System.out.println(l);
答案 0 :(得分:3)
这对我来说似乎是一次学术练习(否则我希望你使用 Java Collections Framework 中的LinkedList<Character>
),所以我不打算发帖一个完整的方法给你。相反,我会试着引导你为你自己创建一个有效的深层复制实现。
首先关闭 - 我不会使用递归来复制您的列表。如果你这样做,你可能会遇到StackOverflowError
,因为你的列表变得越来越大(诚然,对于三元素列表来说,这不会是一个问题)。其次,不是让构造函数返回你给它的CharLinkedList
的深层副本,而是覆盖Object
的{{1}}方法(毕竟这就是它的用法)。
您如何将每个元素复制到克隆列表中?
嗯,您已经知道列表的大小,您将其存储在clone()
属性中。您可以将此值用作size
循环的上限,您可以在其中按顺序复制每个列表元素。
由于您的for
类仅维护对 head 元素的引用,因此您需要在外部维护对当前 CharLinkedList
的引用你的循环,否则你会在每次迭代后失去对下一个元素的引用。
从本质上讲,你需要像这样的伪代码:
Node
完成后,CharLinkedList newList = new CharLinkedList();
Node currentNode = head;
// There are plenty of other ways to do this, you could also use a while loop
// checking that next is not null.
for (each element up until size) {
// You may need to implement getData()
Node newNode = new Node(currentNode.getData());
newList.add(newNode);
// You may need to implement getNextNode()
currentNode = currentNode.getNextNode();
}
,并且不要忘记记录您的return newList
方法返回深层克隆而不是浅层克隆< / em>的。为什么? 因为这是一个很好的习惯。
最后,不要忘记查看 Java Collections Framework ,它已经包含了clone()
的实现,您可以通过它的源代码阅读。< / p>
答案 1 :(得分:0)
在CharLinkedList
接受另一个CharLinkedList
的构造函数中,您只使用if
语句来检查其他链接列表是否有另一个元素,如果有,则会将其添加为this.head.next
。但是,如果有多个元素,则需要将if
语句转换为while
,并使用临时变量node
作为排序的“迭代器”。
这样的事情应该做:
Node node = some.head;
this.head = new Node(some.head.info);
Node adder = this.head; // keep track of the adding nodes
node = node.next; // advance the pointer to the next node
while(node.next != null) // keep adding to the linked list while there are things to add
{
adder.next = new Node(node.info);
node = node.next; // advance the pointer to the next node
}
该代码将遍历some
链接列表,并将其每个元素的副本复制到当前正在构建的链接列表中。
您的addAll
计划存在一些缺陷。添加所有元素的最明确的方法是实现类似于我上面写的解决方案,修改开始添加的位置等。但是,在解决当前样式的情况下,仅使用CharLinkedList的addAll
是好的,并使用其他参数正确调用递归addAll
,但是在您正在检查的其他addAll
中
if(node.next == null)
即使你从前一个函数传递它node.next
,预计它仍然是null
。此外,您不能总是添加第0个元素,因为这可能是一个深度递归调用链中的几个链接。要继续此实现,您可以添加一个额外的int
参数来跟踪列表中的位置,或者添加一个额外的Node
参数来指定接下来要添加的内容 - 选择/ stye是您的。
希望这有帮助