是否有一个Java堆实现可以在O(logn)时间内删除任意对象?

是否有一个Java堆实现可以在O(logn)时间内删除任意对象?,java,time-complexity,heap,priority-queue,Java,Time Complexity,Heap,Priority Queue,假设我在PriorityQueue中有一组对象,这样我可以方便地确定并删除logn time中的min/max。但假设我还希望能够从PriorityQueue中查找并删除任意对象。堆在最坏的情况下需要时间才能找到对象。一旦删除,上下冒泡恢复heap属性需要很长时间 但是我可以很容易地想象一个堆的实现,它补充了一个HashMap,它跟踪每个对象所在的索引。然后,要删除的对象的查找将是O1次,而更正将是Ologn,因此任意对象的删除将是Ologn。这样的数据结构存在吗?您可以使用。它支持在Olog

假设我在PriorityQueue中有一组对象,这样我可以方便地确定并删除logn time中的min/max。但假设我还希望能够从PriorityQueue中查找并删除任意对象。堆在最坏的情况下需要时间才能找到对象。一旦删除,上下冒泡恢复heap属性需要很长时间


但是我可以很容易地想象一个堆的实现,它补充了一个HashMap,它跟踪每个对象所在的索引。然后,要删除的对象的查找将是O1次,而更正将是Ologn,因此任意对象的删除将是Ologn。这样的数据结构存在吗?

您可以使用。它支持在Olog n time delete中按元素删除,还支持首先查找第一个元素和第一个pollFirst。通过使用此接口,您应该能够有效地拥有优先级队列。

正确的方法在于管理一个真正的树,并使用指向子级并最终指向父级的指针。数组的问题是,当您修改堆时,它的条目在数组中移动;这样可以防止在附加数据结构中存储数组索引或指针

使用基于树的实现,您可以完美地存储指向节点的指针,并在Olog n中执行删除操作,前提是重新执行节点的删除操作最多消耗Olog n

<>有一个C++实现,最终可以翻译成java。在这里:

包含实现的文件是


这是一个正确的实现,但由于一些特殊情况,它有些复杂。

如果您使用一个独特的部分扩展比较,您仍然可以引用@Strikeskids使用:

public class Item implements Comparable<Item> {
    private static int next=0;
    private final int ext=next++;
    private final int priority;
    public Item(int priority) {
        this.priority=priority;
    }
    @Override
    public String toString() {
        return priority+" ("+ext+")";
    }
    @Override
    public int compareTo(Item o) {
        if(priority!=o.priority)return priority-o.priority;
        return ext-o.ext;
    }

    public static void main(String[] args) {
        Item a=new Item(5);
        Item b=new Item(5);
        Item c=new Item(6);
        TreeSet<Item> set=new TreeSet<>();
        System.out.println(set.add(a));
        System.out.println(set.add(b));
        System.out.println(set.add(c));
        while(!set.isEmpty()){
            Item i=set.first();
            System.out.println(i);
            set.remove(i);
        }
    }
}

它可以正常工作,直到扩展溢出可以延迟很长时间,然后它可以正常工作。当同时存在正扩展和负扩展时,此阶段进一步延迟的可能性是从Xy.MIN_值开始,而不是从0开始,当扩展溢出时,它会故障,并且确实存在很长的饥饿项,一个新的项目具有匹配的优先级和扩展名。从理论上讲,可以找到/跟踪仍在使用的最低扩展,并将其从所有扩展中减去,包括其本身,作为一些偶尔的内务管理程序的一部分-但是,它仍然无法帮助解决极长时间的饥饿问题。

不是内置的。你必须建造它。复制品有多重要?提到排队。它可以包含重复项。如果可以复制,则映射或设置将不起作用。TreeSet的潜在问题是它不允许复制。因此,每个优先级都必须是唯一的。这将防止在附加数据结构中存储数组索引或指针。不是真的。使用附带的字典编写基于数组的堆非常容易。无论何时更改项目在数组中的位置,都会更新其在字典中的位置。没有角落的箱子,也不需要一棵树。我同意。但是,我认为您必须更新~Olog n数组索引;移除时移动的对象,虽然会留下remove Olog n,但它需要额外的对数迭代。对于基于树的实现,您只需执行一次Olog n迭代。但是是的,你是对的。谢谢你的澄清。