Removing tail element of priority queue

26,144

Solution 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);

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

Solution 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.

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

Solution 5

While you add the data into priority queue itself do the comparison;

PriorityQueue<Integer> pq = new PriorityQueue<Integer>(Collections.reverseOrder());
Share:
26,144
P R
Author by

P R

Noob girl coder

Updated on July 20, 2020

Comments

  • P R
    P R almost 4 years

    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!