Tag: 优先队列

如何实现基于最小堆的优先级队列的O(logn)减less键操作?

我正在开发一个演示Djikstraalgorithm的应用程序,为了使用它,我需要在元素值减less时恢复堆属性。 关于复杂性的问题是, 当algorithm改变元素的值时,用于优先级队列的内部结构(在这种情况下为堆)中的该元素的索引 是未知的 。 因此,我现在需要做一个O(n)的search,以便恢复索引,然后才能对其执行实际的减键 。 而且,我并不完全确定操作所需的实际代码。 我在这里使用D堆作为我的优先级队列。 伪代码将有所帮助,但我更喜欢Java中的一个例子,如何做到这一点。

二进制堆的有效实现

我在寻找如何有效地实现二进制堆的信息 。 我觉得应该有一个好的文章有关实施堆,但我还没有find一个。 事实上我一直没有find任何有关如何将数据堆存储在基础之上的有效实现方面的资源。 我正在寻找制作快速二进制堆的技术,超出了我在下面描述的范围。 我已经写了一个比Microsoft Visual C ++和GCC的std :: priority_queue更快的C ++实现,或者使用std :: make_heap,std :: push_heap和std :: pop_heap。 以下是我在实现中已经涉及到的技术。 我自己只提出了最后两个,但我怀疑这些是新的想法: (编辑:增加内存优化部分) 从1开始索引 查看二维堆的维基百科实现注释 。 如果堆的根位于索引0处,则索引n处的父节点,左节点和右节点的公式分别为(n-1)/ 2,2n + 1和2n + 2。 如果使用基于1的数组,那么公式将变得更简单n / 2,2n和2n + 1.因此,在使用基于1的数组时,父项和左项是更高效的。 如果p指向一个基于0的数组,并且q = p-1,那么我们可以像q [1]那样访问p [0],所以在使用基于1的数组时没有开销。 在更换叶子之前,将popup/移除元素移到堆的底部 在一个堆上popup通常是通过replace最左边的底部叶子的顶部元素,然后将其向下移动直到堆属性被恢复来描述。 这要求每个级别进行2次比较,而且我们可能会在堆栈顶部移动一个叶子,因此可能会走得很远。 所以我们应该期望有less于2个log n的比较。 相反,我们可以在堆顶部留下一个洞。 然后,我们通过迭代地将更大的孩子向上移动,将这个洞向下移动。 这只需要我们通过每个级别1比较。 这样孔就会变成一片叶子。 在这一点上,我们可以将最右边的底部叶子移动到洞的位置,并移动该值直到堆属性恢复。 既然我们移动的价值是一片叶子,我们不期望它移动到树上很远。 所以我们应该期待比log n比较多一点,这比以前更好。 支持replace顶部 假设你想删除最大的元素,并插入一个新的元素。 […]