【问题标题】:Removing tail element of priority queue删除优先队列的尾部元素
【发布时间】:2013-02-13 13:32:42
【问题描述】:

如何删除优先队列的尾部元素?我正在尝试使用优先级队列实现波束搜索,一旦优先级队列已满,我想删除最后一个元素(优先级最低的元素)。

谢谢!

【问题讨论】:

标签: java priority-queue


【解决方案1】:

不支持去掉尾巴。

你能做的最好的事情是交换元素的顺序,让尾部变成头部,然后 remove() 代替它。

【讨论】:

    【解决方案2】:

    当您将数据添加到优先级队列本身时进行比较;

    PriorityQueue<Integer> pq = new PriorityQueue<Integer>(Collections.reverseOrder());
    

    【讨论】:

      【解决方案3】:

      您可能可以使用 Guava 的 MinMaxPriorityQueue 来执行此操作。它为队列的两端提供了 peek、poll 和 remove 方法。

      另一种选择是编写一个强制边界的队列包装器,类似于this answer。您需要实现offeraddaddAll 来检查容量。比如:

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

      【讨论】:

      • 只是好奇,由于 MinMaxPriorityQueue 被标记为 Beta(从 Guava v22.0 开始不稳定),不确定是否建议在生产代码中使用它?
      【解决方案4】:

      如果您有理由不向内存生成另一个元素,有一个更好的解决方案。

      您可以获取队列的大小并在计算要遍历的元素时使用迭代器运行它,一旦您到达最后一个或您正在寻找的那个,您可以使用 PriorityQueue.remove(Object o)

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

      【讨论】:

        【解决方案5】:

        我认为,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;
             }   
            }
        

        【讨论】:

        • else 块的缩进已关闭
        【解决方案6】:

        如果您关心运行时,我建议您实现自己的队列。我做了以下工作并在我的项目中工作。

        1) 从 PriorityQueue -> CustomQueue.java 复制粘贴代码 2) 添加方法 removeLast() 3)这是我使用的实现(非常少)

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

        }

        这样做的原因是 PriorityQueue 的实现使用数组来保存对象。所以“大小”实际上是指向数组中下一个可用点的指针。通过减小它,数组/队列的大小会减小,就像您要删除最后一个元素一样。

        【讨论】:

          【解决方案7】:

          使用反相比较器并从头部移除。如果你需要头部和尾部,那么你使用了错误的数据结构。

          【讨论】:

          • 据我了解,删除优先队列是 O(log(N)) 操作。如果删除操作会做很多事情,那么使用 TreeSet 不会更有效(假设唯一性不是问题),因为这应该是 O(1)
          【解决方案8】:

          不容易。将元素从原始元素复制到新元素,最后一个除外。

          PriorityQueue removelast(PriorityQueue pq)
          {
          
              PriorityQueue pqnew;
          
              while(pq.size() > 1)
              {
                  pqnew.add(pq.poll());
              }
          
              pq.clear();
              return pqnew;
          }
          

          称为

          pq = removelast(pq);
          

          【讨论】:

            猜你喜欢
            • 2020-09-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多