当前位置: 首页 > 面试题库 >

PriorityQueue /堆更新

宇文梓
2023-03-14
问题内容

一旦PriorityQueue中对象的优先级发生更改,Java是否有一种简便的方法来重新评估堆?我在中找不到任何迹象Javadoc,但是必须有某种方法可以做到这一点,对吗?我当前正在删除对象,然后重新添加它,但这显然比在堆上运行更新要慢。


问题答案:

您可能需要自己实现这样的堆。您需要对项目在堆中的位置有一些处理,并需要有一些方法可以在优先级发生变化时向上或向下推项目。

几年前,我在学校工作中写了这么一堆书。向上或向下推动项目是O(log
N)操作。我将以下代码作为公共领域发布,因此您可以随意使用它。(您可能需要改进此类,以便代替抽象的isGreaterOrEqual方法,排序顺序将依赖于Java的Comparator和Comparable接口,并使该类使用泛型。)

import java.util.*;

public abstract class Heap {

    private List heap;

    public Heap() {
        heap = new ArrayList();
    }

    public void push(Object obj) {
        heap.add(obj);
        pushUp(heap.size()-1);
    }

    public Object pop() {
        if (heap.size() > 0) {
            swap(0, heap.size()-1);
            Object result = heap.remove(heap.size()-1);
            pushDown(0);
            return result;
        } else {
            return null;
        }
    }

    public Object getFirst() {
        return heap.get(0);
    }

    public Object get(int index) {
        return heap.get(index);
    }

    public int size() {
        return heap.size();
    }

    protected abstract boolean isGreaterOrEqual(int first, int last);

    protected int parent(int i) {
        return (i - 1) / 2;
    }

    protected int left(int i) {
        return 2 * i + 1;
    }

    protected int right(int i) {
        return 2 * i + 2;
    }

    protected void swap(int i, int j) {
        Object tmp = heap.get(i);
        heap.set(i, heap.get(j));
        heap.set(j, tmp);
    }

    public void pushDown(int i) {
        int left = left(i);
        int right = right(i);
        int largest = i;

        if (left < heap.size() && !isGreaterOrEqual(largest, left)) {
            largest = left;
        }
        if (right < heap.size() && !isGreaterOrEqual(largest, right)) {
            largest = right;
        }

        if (largest != i) {
            swap(largest, i);
            pushDown(largest);
        }
    }

    public void pushUp(int i) {
        while (i > 0 && !isGreaterOrEqual(parent(i), i)) {
            swap(parent(i), i);
            i = parent(i);
        }
    }

    public String toString() {
        StringBuffer s = new StringBuffer("Heap:\n");
        int rowStart = 0;
        int rowSize = 1;
        for (int i = 0; i < heap.size(); i++) {
            if (i == rowStart+rowSize) {
                s.append('\n');
                rowStart = i;
                rowSize *= 2;
            }
            s.append(get(i));
            s.append(" ");
        }
        return s.toString();
    }

    public static void main(String[] args){
        Heap h = new Heap() {
            protected boolean isGreaterOrEqual(int first, int last) {
                return ((Integer)get(first)).intValue() >= ((Integer)get(last)).intValue();
            }
        };

        for (int i = 0; i < 100; i++) {
            h.push(new Integer((int)(100 * Math.random())));
        }

        System.out.println(h+"\n");

        while (h.size() > 0) {
            System.out.println(h.pop());
        }
    }
}


 类似资料:
  • 问题内容: 我在Java整数中有优先级队列: 当我打电话时,我得到了最小的元素。 问题:如何更改代码以获取最大元素? 问题答案: 这样吧: 在提供了一个将在元素进行排序在这种情况下,在该oposite为了自己的自然顺序。

  • 我刚刚开始学习C编程,为了锻炼我找到了这个任务。我必须使用动态、基于数组的整数堆栈编写PriorityQueue。这就是我到目前为止得到的。 提前感谢您的帮助。

  • 问题内容: 如果您不能使用 insertWithPriority, 为什么要命名?看起来非常类似于堆。有什么区别吗?如果没有区别,那为什么命名而不是堆? 问题答案: Add()的工作方式类似于insertWithPriority。 您可以使用构造函数为所需的类型定义优先级: 在http://download.oracle.com/javase/1,5.0/docs/api/java/util/Pr

  • 问题内容: 我正在尝试使用来使用排序对象。 这很容易实现,但是对象类变量(比较器用来计算优先级)在初始插入后可能会更改。大多数人提出了一种简单的解决方案,即删除对象,更新值并再次将其重新插入,因为这是优先级队列的比较器投入使用的时候。 除了围绕PriorityQueue创建包装器类之外,还有其他更好的方法吗? 问题答案: 你必须删除并重新插入,因为队列的工作原理是在插入新元素时将它们放置在适当的位

  • 问题内容: Java标准库中的Priority Queue实现似乎是最小的Priority Queue,我感到有些困惑。为了将其变为最大,我创建了一个自定义比较器对象。 我想知道是否有更优雅的解决方案。从本质上讲,我不会使用可用于实现Dijkstras等的通用优先级队列。我什至没有意识到会有反向操作的队列:/ 问题答案: 使用Java的比较器。 Java参考

  • 我已经实现了从head中提取item,更新它的优先级并将它放回队列的例程(使用AtomicReference) 现在我需要找出队列中的任意条目,更改它的优先级并将其放回队列中。看来PriorityQueue不支持这一点,那么我应该使用哪个类来完成期望的行为呢?