【发布时间】:2013-02-13 13:32:42
【问题描述】:
如何删除优先队列的尾部元素?我正在尝试使用优先级队列实现波束搜索,一旦优先级队列已满,我想删除最后一个元素(优先级最低的元素)。
谢谢!
【问题讨论】:
-
您可以创建一个新的
PriorityQueue实例并将所有元素从初始队列移动到新队列中,除了尾部。
标签: java priority-queue
如何删除优先队列的尾部元素?我正在尝试使用优先级队列实现波束搜索,一旦优先级队列已满,我想删除最后一个元素(优先级最低的元素)。
谢谢!
【问题讨论】:
PriorityQueue 实例并将所有元素从初始队列移动到新队列中,除了尾部。
标签: java priority-queue
不支持去掉尾巴。
你能做的最好的事情是交换元素的顺序,让尾部变成头部,然后 remove() 代替它。
【讨论】:
当您将数据添加到优先级队列本身时进行比较;
PriorityQueue<Integer> pq = new PriorityQueue<Integer>(Collections.reverseOrder());
【讨论】:
您可能可以使用 Guava 的 MinMaxPriorityQueue 来执行此操作。它为队列的两端提供了 peek、poll 和 remove 方法。
另一种选择是编写一个强制边界的队列包装器,类似于this answer。您需要实现offer、add 和addAll 来检查容量。比如:
public class BoundedQueue<E> implements Serializable, Iterable<E>, Collection<E>, Queue<E> {
private final Queue<E> queue;
private int capacity;
public BoundedQueue(Queue<E> queue, int capacity) {
this.queue = queue;
this.capacity = capacity;
}
@Override
public boolean offer(E o) {
if (queue.size() >= capacity)
return false;
return queue.add(o);
}
@Override
public boolean add(E o) throws IllegalStateException {
if (queue.size() >= capacity)
throw new IllegalStateException("Queue full"); // same behavior as java.util.ArrayBlockingQueue
return queue.add(o);
}
@Override
public boolean addAll(Collection<? extends E> c) {
boolean changed = false;
for (E o: c)
changed |= add(o);
return changed;
}
// All other methods simply delegate to 'queue'
}
【讨论】:
如果您有理由不向内存生成另一个元素,有一个更好的解决方案。
您可以获取队列的大小并在计算要遍历的元素时使用迭代器运行它,一旦您到达最后一个或您正在寻找的那个,您可以使用 PriorityQueue.remove(Object o)
Iterator<E> it = Queue.iterator();
while (it.hasNext()) {
temp<E> = it.next();
counter++;
if (counter == Queue.size()) {
Queue.remove(temp);
}
}
【讨论】:
我认为,PR的用例是,他需要头部,但也想要有一个小的PQ,所以想法是去除尾部。
由于 PQ 被实现为映射到数组的二叉树,所以头部始终是后备数组 (queue[0]) 的第一个元素,但尾部并不总是位于数组的末尾,您必须搜索一下。
我认为一个不错的方法是继承 PQ 并编写以下两个方法:
public class MyPriorityQueue<E> extends PriorityQueue<E>
{
// constructors
public E getTail()
{
// queue.length can be bigger than this.size() !!
Object[] queue = this.toArray();
E tail = (E)queue[0];
Comparator<? super E> comparator = this.comparator();
if (comparator !=null)
for(int i = 1; i < this.size(); i++)
if ( comparator.compare(tail, (E)queue[i]) < 0)
tail = (E)queue[i];
else
for(int j = 1; j < this.size(); j++)
if ( ((Comparable)tail).compareTo( ((Comparable)queue[j]) ) < 0 )
tail = (E)queue[j];
return tail;
}
public E removeTail()
{
E tail = this.getTail();
this.remove(tail);
return tail;
}
}
【讨论】:
如果您关心运行时,我建议您实现自己的队列。我做了以下工作并在我的项目中工作。
1) 从 PriorityQueue -> CustomQueue.java 复制粘贴代码 2) 添加方法 removeLast() 3)这是我使用的实现(非常少)
public void removeLast() {
if(size == 0) {
return;
}
queue[size - 1] = null;
size--;
}
这样做的原因是 PriorityQueue 的实现使用数组来保存对象。所以“大小”实际上是指向数组中下一个可用点的指针。通过减小它,数组/队列的大小会减小,就像您要删除最后一个元素一样。
【讨论】:
使用反相比较器并从头部移除。如果你需要头部和尾部,那么你使用了错误的数据结构。
【讨论】:
不容易。将元素从原始元素复制到新元素,最后一个除外。
PriorityQueue removelast(PriorityQueue pq)
{
PriorityQueue pqnew;
while(pq.size() > 1)
{
pqnew.add(pq.poll());
}
pq.clear();
return pqnew;
}
称为
pq = removelast(pq);
【讨论】: