【发布时间】:2015-12-17 09:30:30
【问题描述】:
我有一个整数流,以及一个由用户给出的 int k。在程序结束时,我必须打印 k 个最高的数字。我只能使用容量为 k 的优先级队列。
我的问题是当队列达到满容量时,下一个整数读取必须替换队列中的最低值。
如何在插入后保持队列排序,以便知道在下一次迭代中替换哪个 int,复杂度为 O(logn)?我使用了一种游泳方法(如下所示),但是,虽然它会将新的 int 放置在正确的级别,但它不会使队列完全排序。
游泳方法如下:
private void swim(int i){
while (i > 1) { //if i root (i==1) return
int p = i/2; //find parent
int result = cmp.compare(heap[i], heap[p]); //compare parent with child
if (result == 1) return; //if child <= parent return
swap(i, p); //else swap and i=p
i = p;
}
}
为了让自己更清楚,这里有一个 k = 3 的例子。
1: A = 42 / B = null / C = null
2: A = 69 / B= 42 / C = null (69 swims upwards)
3: A = 69 / B= 42 / C = 32
4: A = 69 / B= 42 / C = 32 (no change)
5: A = 104 / B= 42 / C = 69 (104 is inserted replacing 32, then swims upwards)
6: A = 104 / B= 42 / C = 93 (93 is inserted replacing 69, remains there)
【问题讨论】:
-
目前还不清楚你想要实现什么。如果队列的大小小于
k,则元素按其自然顺序排序(PriorityQueue 的默认行为)。当队列的大小等于k时,元素按插入顺序排序,最后一个元素被下一个添加的元素替换?是否应该从队列中删除前一个最后一个元素? -
@SubOptimal。就像你说的,最低的元素应该被下一个添加的元素替换(如果它更大)。问题是有时会替换错误的元素。在示例中,93 将替换 69 而不是 42。
-
遵循哪个规则
104在索引A的第4步之后设置并且交换了69和42的顺序?为了与您在第 5 步中所说的一致,应该改为 69、42、104。 -
@SubOptimal 抱歉,打错了。在第 5 步,在右下角插入 104(不是 69),替换 32。然后,swim 使其与顶部的 69 切换位置。
-
您应该查看您的示例。现在我们知道
104的来源。但是为什么在第 5 步中,69,42(来自第 4 步)的顺序在第 5 步变成了(42,69)?为什么在第 6 步93替换69而不是42?这不符合您的next integer read must replace the lowest in the queue。你对java.util.PriorityQueue的限制是什么?队列中的所有 k 个元素是否应该始终按其自然顺序排序?
标签: java tree heap priority-queue