在我的链表实现中,有两种方法。当我调用一个方法时,它会影响另一个方法的结果。一种方法是concatenateLL()
来连接两个列表,一种方法是getNumberOfNodes()
,它返回链表中的节点数。对于我的方法连接,我应该返回一个新列表,它是两个列表的串联。但是在我的代码中,生成的新列表会影响第一个参数中的列表。让我说我传递列表l
和m
和参数,然后我返回一个新列表。
问题是新的只是列表l
,它现在包含列表m
的元素(由于连接)。因此,当我在列表getNumberOfNodes()
和l
上调用m
时,我得到了错误的值。
这是我的代码:
public static LinkedList concatenateLL(LinkedList l, LinkedList m) {
LinkedList a = l;
Node l_last = a.getTailNode();
Node m_first = m.getHeadNode();
l_last.setNext(m_first);
a.tail = m.getTailNode();
return a;
}
public int getNumberOfNodes(Node h) {
if(h == null)
return 0;
return 1 + getNumberOfNodes(h.getNext());
}
public static void print(LinkedList l) {
Node v = l.getHeadNode();
while(v != null) {
System.out.print(v.getElement()+" ");
v = v.getNext();
}
System.out.println();
}
public static void main(String[] args) throws IndexOutOfBoundsException {
// TODO Auto-generated method stub
LinkedList l = new LinkedList();
LinkedList m = new LinkedList();
l.insertFirst(5);
l.insertFirst(7);
l.insertFirst(3);
l.insertFirst(6);
print(l);
m.insertFirst(2);
m.insertFirst(4);
m.insertFirst(9);
m.insertFirst(8);
m.insertLast(10);
m.insertLast(12);
print(m);
LinkedList n = concatenateLL(l, m);
print(n);
System.out.println(l.getNumberOfNodes(l.getHeadNode()));
System.out.println(m.getNumberOfNodes(m.getHeadNode()));
}
在主要方法中,列表l
的长度应返回4
,列表m
应返回6
。但是在我调用getNumberOfNodes()
之前调用连接方法之后,我得l
的长度为10
(这是n
的节点数,因为{{{}}连接的结果1}}和l
)以及m
的长度为m
(我不明白为什么)。
答案 0 :(得分:1)
当我看到你的代码时,我猜你习惯用C / C ++编写(基于命名约定和预期行为)。您的问题在于进行深层复制。在concatenateLL
方法的开头,您需要对两个列表进行深层复制,然后您可以按照当前的方式将它们连接起来。
LinkedList a = l; // problem line
在C / C ++中,它会调用一个复制构造函数,但是Java没有这样的东西,所以你需要自己实现它。您可以使用clone()
声明的方法java.lang.Object
并覆盖它,但您需要使深层复制不浅,因为您还要更改节点之间的引用,而不仅仅是列表
例如,该方法可能看起来像这样:
public static LinkedList concatenateLL(LinkedList l, LinkedList m) {
LinkedList a = new LinkedList();
// copy Nodes, you need to create new instance of them
for ( int i = 0; i < l.getNumberOfNodes(l.getHeadNode()); ++i )
a.insertLast( l.getNode( i ) );
// copy Nodes, you need to create new instance of them
for ( int i = 0; i < m.getNumberOfNodes(m.getHeadNode()); ++i )
a.insertLast( m.getNode( i ) );
return a;
}
但我需要提一下,由于方法O(n^2)
为getNode()
,此实施的复杂度为O(n)
。更好的解决方案是使用迭代器,但我不知道你的类是否实现它。
修改强>
为了提高O(n)
的复杂性,我建议你实现标准接口Iterator无论如何,重点在于保持对当前元素的引用能够简单地获得下一个。如果我举一个简单的例子:
Node item = l.getHeadNode();
while( item != null ) {
// copy the item
a.insertLast( item );
item = item.getNext();
}
列表m
也一样。
答案 1 :(得分:0)
是的,LInkedList a = l;
不会创建链接列表l
的副本。
如果您不想修改l
,则必须创建新的链接列表。
答案 2 :(得分:0)
public static LinkedList concatenateLL(LinkedList l, LinkedList m) {
LinkedList a = new LinkedList();
Node l_last = l.getHeadNode();
Node m_first = m.getHeadNode();
while(l_last != null) {
a.insertLast(l_last.getElement());
l_last = l_last.getNext();
}
while(m_first != null) {
a.insertLast(m_first.getElement());
m_first = m_first.getNext();
}
return a;
}