我正在将一个C ++库移植到Java,我需要一个堆数据结构。有标准吗? 实施还是我需要自己做?
答案 0 :(得分:61)
熟悉Priority Queue。应该这样做
答案 1 :(得分:10)
在Java PriorityQueue中可用作堆。
最小堆
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
最大堆:
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
答案 2 :(得分:6)
PriorityQueue使用堆。基于https://docs.oracle.com/javase/8/docs/api/java/util/PriorityQueue.html的oracle文档,它似乎是二进制堆的实现。我不认为有斐波那契或配对堆的官方实施,但我很乐意看到两者中的任何一个可用。
答案 3 :(得分:3)
没有,虽然没有,但是您可以将Priority Queue用作堆。 Oracle正式通知其使用Priority Queue作为堆,您也可以参考this link进行进一步说明。
PriorityQueue<Integer> MinHeap = new PriorityQueue<>();
PriorityQueue<Integer> MaxHeap = new PriorityQueue<>(Comparator.reverseOrder());
答案 4 :(得分:2)
最小堆:
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
最大堆:
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return - Integer.compare(o1,o2);
}
});
答案 5 :(得分:2)
对于Java 8,在现有answer上更新:
您可以将Java Priority Queue用作堆。
最小堆:->将min元素始终放在顶部,因此您可以在O(1)中访问它。
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
最大堆:->将max元素始终放在顶部,顺序与上面相同。
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((Integer o1, Integer o2) -> (- Integer.compare(o1,o2)));
您可以使用:
add
->将元素添加到队列。 O(log n)
remove
->获取和删除最小值/最大值。 O(log n)
peek
->获取,但不删除最小值/最大值。 O(1)
答案 6 :(得分:0)
您还可以考虑TreeSet,它保证了基本操作的log(n)时间(添加,删除,包含)。
答案 7 :(得分:0)
来自 Java 文档 PriorityQueue
,自 1.5 以来可用,是要使用的类。
Min Heap
的这段代码创建了一个具有默认初始容量 (11) 的 PriorityQueue,它根据元素的 natural ordering 对其元素进行排序,其中最小值位于顶部。
//MIN HEAP
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
//equivalent to
PriorityQueue<Integer> minHeap = new PriorityQueue<>(11);
如果你想实现一个特殊的排序,你需要用这个构造函数覆盖比较器
PriorityQueue(int initialCapacity, Comparator<? super E> comparator);
从 1.8 开始我们也有这个版本
PriorityQueue(Comparator<? super E> comparator);
它可以帮助您以更优雅的方式创建 Max Heap
,例如
//MAX HEAP
PriorityQueue<Integer> maxHeap =
new PriorityQueue<>((n1,n2) -> Integer.compare(n2,n1));
//equivalent to
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
对于特殊情况,请查看此示例,该示例显示了自定义对象的自然排序,在我们根据客户与虚构餐厅的距离进行排序的情况下
import java.util.List;
import java.util.PriorityQueue;
public class DeliveryHandler {
private static final Address restaurant = new Address(5.0, 5.0);
private static class Address implements Comparable<Address> {
public double x, y;
public Address(double x, double y) {
this.x = x;
this.y = y;
}
public double distanceToShop() {
return Math.pow(restaurant.x - x, 2) + Math.pow(restaurant.y - y, 2);
}
@Override
public int compareTo(Address other) {
return Double.compare(this.distanceToShop(), other.distanceToShop());
}
@Override
public String toString() {
return "Address {x=%s, y=%s}".formatted(x, y);
}
}
public static void main(String[] args) {
List<Address> customers = List.of(
new Address(13, 14),
new Address(3, 1),
new Address(9, 20),
new Address(12, 4),
new Address(4, 4));
PriorityQueue<Address> queueServingClosest = new PriorityQueue<>();
queueServingClosest.addAll(customers);
while (!queueServingClosest.isEmpty()) {
System.out.println(queueServingClosest.remove());
}
/* Prints
Address {x=4.0, y=4.0}
Address {x=3.0, y=1.0}
Address {x=12.0, y=4.0}
Address {x=13.0, y=14.0}
Address {x=9.0, y=20.0}
*/
PriorityQueue<Address> queueServingFurthest = new PriorityQueue<>(
(a1, a2) -> Double.compare(a2.distanceToShop(), a1.distanceToShop())
);
queueServingFurthest.addAll(customers);
while (!queueServingFurthest.isEmpty()) {
System.out.println(queueServingFurthest.remove());
}
/* Prints
Address {x=9.0, y=20.0}
Address {x=13.0, y=14.0}
Address {x=12.0, y=4.0}
Address {x=3.0, y=1.0}
Address {x=4.0, y=4.0}
*/
}
}
参考
1- https://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html
2- https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/PriorityQueue.html