LinkedList上的帖子说:
LinkedList允许恒定时间插入或删除,但只允许顺序访问元素。换句话说,you can walk the list forwards or backwards, but grabbing an element in the middle
需要的时间与列表的大小成正比。
我不明白什么才有资格抓住中间的元素?
在下面的代码中,假设arrL
是一个包含50个elemnet的LinkedList,当计数器j
达到20时,程序执行arrL.get(20)
..这是否意味着程序正在抓取中间元素?同样在下面的程序中,我只是向前走,不是吗?
for(int j=0;j<arrL.size();++j){
arrL.get(j);
}
答案 0 :(得分:8)
是的,在每次迭代中,您从头到尾遍历第j 个元素,因此整体循环性能为n^2
(非常差)。这是因为在每次迭代中,您都有独立的get()
调用,它具有线性性能。
另一方面,如果使用迭代器,您将一次遍历列表一个元素,在每次迭代中前进一个元素,这要快得多:
for(Iterator<E> iter = arrL.iterator(); iter.hasNext();) {
E e = iter.next();
}
或更好:
for(E k: arrL) {
}
BTW这是一个非常的基本数据结构问题,Java在这里无关......
答案 1 :(得分:1)
对于LinkedList,get(N)需要与N成比例的时间。所以 - get(19)大约是get(0)的20倍。上面的for循环在O(n ^ 2)时间内运行 - n遍,每次通过O(n)时间。如果要按顺序访问成员,请使用迭代器:
Iterator it = arrL.iterator();
while(it.hasNext()) {
it.next();
}
或暗示,如此:
for(Obj o : arrL) {
// do something with o
}
答案 2 :(得分:0)
在链表中,每个列表条目只知道其前任及其后继:它们只是相互链接。关于这一点的好处是,只需添加和链接到新元素就可以轻松地使这个列表增长。但是到达列表中不是端点的元素需要从任一端走到特定元素。因此,每次调用get(j)
都需要从链/列表中的端点进行j
元素访问。换句话说,get(j)
在时间上相当昂贵。例如,如果列表包含1000个元素,则获取元素编号500需要从任一端进行500次访问。如果列表长度为2000个元素,那么到中间元素(元素1000)同样需要1000次访问,因为我们遵循节点链接(链)。
相反,访问数组中的任何元素都需要一段时间。
答案 3 :(得分:0)
@Vicky,这意味着每次调用arraL.get(j)
时,此操作都需要线性时间才能执行。这意味着当你获得第20个元素时,它将从头开始(或结束,我不确定实现)并将整个列表横向扩展到第20个元素。
另一个实现ArrayList
将在恒定时间内执行此操作(内部保留数组,因此您可以将arrL.get(20)
视为array[20]
),但每次删除中间的项目时,它必须移动数组中的元素。
所以基本上,对于随机读取,ArrayList
是一个更好的选择,性能明智,当你执行大量删除时,LinkedList
是更好的选择。