当前位置: 首页 > 知识库问答 >
问题:

在Java优先级队列实现删除方法中,为什么它在筛选后进行筛选?

狄宾实
2023-03-14

我一直在阅读Java collection API,这是优先级队列部分,由两位大师Josh Bloch和Doug Lea实现。

JavaPriorityQueue是用数组堆实现的。

代码片段在这里,来自PriorityQueue.java,第600行:

/**
 * Removes the ith element from queue.
 *
 * Normally this method leaves the elements at up to i-1,
 * inclusive, untouched.  Under these circumstances, it returns
 * null.  Occasionally, in order to maintain the heap invariant,
 * it must swap a later element of the list with one earlier than
 * i.  Under these circumstances, this method returns the element
 * that was previously at the end of the list and is now at some
 * position before i. This fact is used by iterator.remove so as to
 * avoid missing traversing elements.
*/

private E removeAt(int i) {
        // assert i >= 0 && i < size;
        modCount++;
        int s = --size;
       if (s == i) // removed last element
            queue[i] = null;
        else {
            E moved = (E) queue[s];
            queue[s] = null;
            siftDown(i, moved);
            //the code I am asking is below:
            if (queue[i] == moved) {
               siftUp(i, moved);
                if (queue[i] != moved)
                    return moved;
            }
        }
        return null;
    }

我想知道的是,移动的元素,过去在堆的底部,应该是i子树中的一个大元素。siftDown方法是合理的,在一个siftDown之后,子树中最小的将被提升到位置i

问题是,如果i没有改变,也就是说,在siftDown之后,被移动的子树仍然存在,在我看来,子树已经被重设了,它不需要再次被重设为siftUp

为什么乔希又把它们举到了顶端?

希望那些读过代码的人能有所帮助!

共有1个答案

东方智敏
2023-03-14

问题是移动的项目(队列[size-1]中的项目)可能与被删除的项目不在同一个子树中。考虑这个堆:

      0
  4       1
5   6   2   3

现在,如果移除节点5,您将拥有:

      0
  4       1
    6   2   3

取堆中的最后一个节点,3,并把它放在5的位置:

      0
  4       1
3   6   2   

你筛选了3个,但它已经是一片叶子了。这可能不合适。你必须对其进行筛选,以获得:

      0
  3       1
4   6   2   
 类似资料:
  • 优先级队列对每个条目都有一个优先级值和数据。 因此,当向队列中添加新元素时,如果该元素的优先级值高于集合中已有的元素,则该元素会浮上表面。 当调用pop时,我们将获得具有最高优先级的元素的数据。 这种优先级队列在JavaScript中的高效实现是什么? 有一个名为PriorityQueue的新对象,创建两个方法(push和pop)来获取两个参数(数据、优先级),这有意义吗?作为一个编码器,这对我来

  • 我正在尝试在滑动窗口中打印最大值。将窗口大小的元素,这里k=3放入优先级队列(Maxheap),然后查看值。”heap.Init(

  • 我正在编写一个涉及堆实现的代码,在我的bubbleUp方法中,在我的while循环行中,我似乎遇到了一个取消引用的错误。这可能是一个相当基本的问题,但解决这个问题的最佳方法是什么?我在实现removeHigh方法时也遇到了一些问题,该方法旨在从队列中移除最高的元素。

  • 我正在实现一个应用程序,该应用程序根据曼哈顿距离查找(x,y)平面中给定位置的最近n个事件。我使用最大优先级队列来存储找到的事件,并使用曼哈顿距离比较器。这个队列应该总是有最大人距离事件作为它的窥视,但是我发现这不会一直发生。我在循环中使用pq.poll()打印了这个队列的结果,我发现队列在删除后没有重新排列,只是有时。 我的比较者: 以主方法打印: 输出: 如您所见,事件不是按降序排列的!然而,

  • 本文向大家介绍什么是Java优先级队列(Priority Queue)?相关面试题,主要包含被问及什么是Java优先级队列(Priority Queue)?时的应答技巧和注意事项,需要的朋友参考一下 考察点:队列 PriorityQueue是一个基于优先级堆的无界队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。Priori

  • 我目前正在尝试实现min heap PQ,但是我在实现的正确性方面遇到了一些问题,我似乎无法找出我做错了什么——它没有输出最低优先级,也没有对它们进行正确排序。 使用以下测试数据: 我得到以下结果: 我希望结果是按升序排列的——起初我认为这可能是因为交换了错误的孩子,但最后一个输出是最大的优先级,所以这没有意义。我花了几个小时试图研究堆优先级队列,但我找不到任何帮助。 以下是CMP要求的更好的代码