有没有办法真正快速地跳转到双向链接列表的中间元素而不是
for(int i = 0; i <= numOfElements/2; i++){
element = element.next;
}
在我的代码中需要这么多时间,如果我会对它进行优化,那真的很酷:)
答案 0 :(得分:10)
链接(或双重链接)列表的要点是随机访问速度很慢(O(n)
)。
您需要使用其他类型的列表,例如skip list。
答案 1 :(得分:5)
链表的重点是无法做到这一点。但是,存在(间接)允许该操作的其他数据结构。一个这样的数据结构是skip list,其名称来源于它可以精确地执行:跳过项目。
此数据结构不能直接应用于您的情况,因为跳过列表实现了词典,不允许直接访问索引项。但是,一般结构可以相应调整。
答案 2 :(得分:0)
我不确定这样做有多大意义取决于你需要一个双向链表的原因。理想情况下,您可以选择不使用它。但是如果不是这样的话,你可以用另一种类型的数据结构支持它,例如带有整数作为键的hashmap。那么你可以这样:
element.get(numOfElements/2);
答案 3 :(得分:0)
当你说“跳到中间”时,你的意思是每次都是确切的中间元素吗?或者只是“除了开头或结尾之外的某个地方,但确切的地方会有所不同”?
如果你的意思是确切的中间,你可以保持一个指向列表中间的指针以及通常的开始和结束指针。每次在列表中添加或删除条目时,都可能需要移动此指针。请注意,两侧需要两个插件才能将其移动一个位置,下方的一个插件和上方的一个插件将被取消。所以你必须保持一个“半柜台”。当下面插入一个项目时,从半个计数器中减去一个。在上面插入项目时,添加一个。如果半计数器现在为-2,则将中间指针向下移动一个插槽并将半计数器复位为0.如果半计数器现在为+2,则将中间指针向上移动一个插槽并复位半计数器。我曾在几年前这样做过。我忘记了原因。
如果你的意思不是确切的中间,那么我认为答案是“它无法完成”。我想,你可以在列表中保留一些指向各个点的指针。就像有一个带有第一个A,第一个B等标签的字典
或者我想如果你知道你经常需要“非常接近中间”,你可以保持一个中间指针,如上所述,然后从那里搜索。
这是否有助于解决您真正想要解决的问题,如果没有更多信息,我不能说。
答案 4 :(得分:0)
你可以保留一个中间指针,但每次更新列表时都需要调整,如果你只需要一个足够的近似值
或保留2个单独的列表,每次访问中间时都要调整它们,直到它们长度相等(保持长度作为每个的单独变量)
public class DoubledLickedList{
private Node fhead,ftail,shead,stail;
private AtomicInteger fsize,sSize;
public Class Node{
private Node next;
private Node prev;
public Node getNext(){
if(next==null && next==ftail)return shead;
return next;
}
public Node getPrev(){
if(prev==null && prev==shead)return ftail;
return prev;
}
}
public Node getMiddle(){
adjustToMiddle();
return ftail;
}
private void adjustToMiddle(){
while(fsize.get()>sSize.get()+1){
//pop first and push it to the second
fsize.incrementAndGet();
sSize.decrementAndGet();
}
while(sSize.get()>fsize.get()+1){
//pop second and push it to the first
sSize.incrementAndGet();
fsize.decrementAndGet();
}
}
}
答案 5 :(得分:0)