Removing tail element of priority queue

最后都变了- 提交于 2019-12-22 05:05:16

问题


How can I remove the tail element of a priority queue? I am trying to implement beam search using a priority queue and once the priority queue is full, I want to remove the last element(the element with the least priority).

Thanks!


回答1:


No easy way. Copy elements from original to new except the last.

PriorityQueue removelast(PriorityQueue pq)
{

    PriorityQueue pqnew;

    while(pq.size() > 1)
    {
        pqnew.add(pq.poll());
    }

    pq.clear();
    return pqnew;
}

called as

pq = removelast(pq);



回答2:


You could probably use Guava's MinMaxPriorityQueue to do this. It provides peek, poll, and remove methods for both ends of the queue.

Another option is to write a Queue wrapper that enforces bounding, similar to this answer. You'd need to implement offer, add, and addAll to check capacity. Something like:

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'
}



回答3:


Use an inverting Comparator and remove from the head. If you need both the head and the tail you are using the wrong data structure.




回答4:


I think, PR's use case is, that he needs the head, but also want to have a small PQ, so the idea is to remove the tail.

As a PQ is realized as a binary tree mapped to an array, the head is always the first element of the backing array (queue[0]), but the tail is not always at the end of the array, you had to search it.

I think a nice way is to subclass PQ and write the following two methods:

    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;
     }   
    }



回答5:


There is a better solution in case you have a reason not to generate another element to the memory.

you can get the size of the Queue and run over it with an iterator while counting the elements you are going over, once you get to the last one OR the one you are looking for, you can use PriorityQueue.remove(Object o)

Iterator<E> it = Queue.iterator();
while (it.hasNext()) {
   temp<E> = it.next();
   counter++;
   if (counter == Queue.size()) {
       Queue.remove(temp);
    }
}



回答6:


If you are concerned with the runtime, I suggest implementing your own queue. I did the following and worked in my project.

1) copy paste the code from PriorityQueue -> CustomQueue.java 2) Add a method removeLast() 3) This is the implementation I used (very minimal)

public void removeLast() {
    if(size == 0) {
       return;
    }
    queue[size - 1] = null;
    size--;

}

The reason this works is that the implementation of PriorityQueue uses an array to hold object. So "size" is infact a pointer to the next available spot in the array. By reducing it, the size of the array/queue is reduced, as if you are dropping the last element.



来源:https://stackoverflow.com/questions/15117246/removing-tail-element-of-priority-queue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!