Удаление хвостового элемента приоритетной очереди

Как удалить хвостовой элемент приоритетной очереди? Я пытаюсь реализовать поиск луча, используя очередь приоритетов, и как только очередь приоритетов заполнена, я хочу удалить последний элемент (элемент с наименьшим приоритетом).

Спасибо!


person P R    schedule 27.02.2013    source источник
comment
Вы можете создать новый экземпляр PriorityQueue и переместить все элементы из начальной очереди в новую, кроме хвоста.   -  person Luiggi Mendoza    schedule 27.02.2013
comment
stackoverflow.com/questions/7878026/   -  person NPE    schedule 27.02.2013


Ответы (8)


Нет простого пути. Скопируйте элементы из оригинала в новый, кроме последнего.

PriorityQueue removelast(PriorityQueue pq)
{

    PriorityQueue pqnew;

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

    pq.clear();
    return pqnew;
}

называется как

pq = removelast(pq);
person user93353    schedule 27.02.2013

Возможно, вы могли бы использовать MinMaxPriorityQueue от Guava. для этого. Он предоставляет методы просмотра, опроса и удаления для обоих концов очереди.

Другой вариант — написать оболочку Queue, обеспечивающую ограничение, подобно этому ответу. Вам нужно будет реализовать 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'
}
person matts    schedule 27.02.2013
comment
Просто любопытно, поскольку MinMaxPriorityQueue помечен как бета-версия (нестабильная версия Guava v22.0), не уверен, рекомендуется ли использовать ее в производственном коде? - person Dravidian; 30.07.2020

Используйте инвертирующий компаратор и снимите его с головы. Если вам нужны и голова, и хвост, вы используете неправильную структуру данных.

person user207421    schedule 27.02.2013
comment
Насколько я понимаю, удаление приоритетной очереди - это операция O (log (N)). Если операция удаления - это то, что будет выполняться много, не будет более эффективным использовать TreeSet (при условии, что уникальность не является проблемой), поскольку это должно быть O (1) - person Nicolas Guillaume; 27.01.2021

Я думаю, вариант использования 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;
     }   
    }
person max    schedule 02.02.2015
comment
ваш отступ блока else отключен - person manonthemat; 20.09.2016

Пока вы добавляете данные в очередь приоритетов, сами выполняйте сравнение;

PriorityQueue<Integer> pq = new PriorityQueue<Integer>(Collections.reverseOrder());
person Vanji    schedule 12.04.2020

Есть лучшее решение, если у вас есть причина не генерировать еще один элемент в память.

вы можете получить размер очереди и запустить ее с помощью итератора, подсчитывая элементы, которые вы просматриваете, как только вы доберетесь до последнего ИЛИ того, который вы ищете, вы можете использовать PriorityQueue.remove(Object o)

Iterator<E> it = Queue.iterator();
while (it.hasNext()) {
   temp<E> = it.next();
   counter++;
   if (counter == Queue.size()) {
       Queue.remove(temp);
    }
}
person T-G    schedule 06.11.2017

Удаление хвоста не поддерживается.

Лучшее, что вы можете сделать, это изменить порядок элементов так, чтобы хвост стал головой, а вместо этого remove().

person Ilya Gazman    schedule 19.07.2020

Если вас беспокоит среда выполнения, я предлагаю реализовать собственную очередь. Я сделал следующее и работал над своим проектом.

1) скопируйте и вставьте код из PriorityQueue -> CustomQueue.java 2) Добавьте метод removeLast() 3) Это реализация, которую я использовал (очень минимальная)

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

}

Причина, по которой это работает, заключается в том, что реализация PriorityQueue использует массив для хранения объекта. Таким образом, «размер» фактически является указателем на следующее доступное место в массиве. Уменьшая его, размер массива/очереди уменьшается, как будто вы отбрасываете последний элемент.

person Ehsan    schedule 12.03.2014