Heap Dijkstra算法。作为最小优先级队列的最小堆
我正在阅读《CLRS》第三版(第662页)中的Dijkstra算法。这是书中我不明白的一部分: 如果图足够稀疏-特别是,Heap Dijkstra算法。作为最小优先级队列的最小堆,heap,priority-queue,dijkstra,min-heap,Heap,Priority Queue,Dijkstra,Min Heap,我正在阅读《CLRS》第三版(第662页)中的Dijkstra算法。这是书中我不明白的一部分: 如果图足够稀疏-特别是,E=o(V^2/lg V)-我们可以通过使用二进制最小堆实现最小优先级队列来改进算法 为什么图形应该是稀疏的 以下是另一部分: 每次减少按键操作都需要时间O(log V),并且仍有 最多只能对此类操作进行重新评估 假设我的图表如下所示: 我想计算从1到6的最短路径,并使用最小堆方法。首先,我将所有节点添加到最小优先级队列中。构建min堆后,min节点就是源节点(因为它与自身
E=o(V^2/lg V)
-我们可以通过使用二进制最小堆实现最小优先级队列来改进算法
为什么图形应该是稀疏的
以下是另一部分: 每次减少按键操作都需要时间
O(log V)
,并且仍有
最多只能对此类操作进行重新评估
假设我的图表如下所示:
我想计算从1到6的最短路径,并使用最小堆方法。首先,我将所有节点添加到最小优先级队列中。构建min堆后,min节点就是源节点(因为它与自身的距离为0)。我提取它并更新它所有邻居的距离
然后我需要在距离最小的节点上调用decreaseKey
,以使堆达到新的最小值。但我如何知道它在恒定时间内的指数呢
节点
private static class Node implements Comparable<Node> {
final int key;
int distance = Integer.MAX_VALUE;
Node prev = null;
public Node(int key) {
this.key = key;
}
@Override
public int compareTo(Node o) {
if (distance < o.distance) {
return -1;
} else if (distance > o.distance) {
return 1;
} else {
return 0;
}
}
@Override
public String toString() {
return "key=" + key + " distance=" + distance;
}
@Override
public int hashCode() {
return key;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Node)) {
return false;
}
Node other = (Node) obj;
return key == other.key;
}
}
public static class MinPriorityQueue {
private Node[] array;
private int heapSize;
public MinPriorityQueue(Node[] array) {
this.array = array;
this.heapSize = this.array.length;
}
public Node extractMin() {
Node temp = array[0];
swap(0, heapSize - 1, array);
heapSize--;
sink(0);
return temp;
}
public boolean isEmpty() {
return heapSize == 0;
}
public void buildMinHeap() {
for (int i = heapSize / 2 - 1; i >= 0; i--) {
sink(i);
}
}
public void decreaseKey(int index, Node key) {
if (key.compareTo(array[index]) >= 0) {
throw new IllegalArgumentException("the new key must be greater than the current key");
}
array[index] = key;
while (index > 0 && array[index].compareTo(array[parentIndex(index)]) < 0) {
swap(index, parentIndex(index), array);
index = parentIndex(index);
}
}
private int parentIndex(int index) {
return (index - 1) / 2;
}
private int left(int index) {
return 2 * index + 1;
}
private int right(int index) {
return 2 * index + 2;
}
private void sink(int index) {
int smallestIndex = index;
int left = left(index);
int right = right(index);
if (left < heapSize && array[left].compareTo(array[smallestIndex]) < 0) {
smallestIndex = left;
}
if (right < heapSize && array[right].compareTo(array[smallestIndex]) < 0) {
smallestIndex = right;
}
if (index != smallestIndex) {
swap(smallestIndex, index, array);
sink(smallestIndex);
}
}
public Node min() {
return array[0];
}
private void swap(int i, int j, Node[] array) {
Node temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
私有静态类节点实现可比较{
最终整数键;
int距离=整数最大值;
Node prev=null;
公共节点(int键){
this.key=key;
}
@凌驾
公共整数比较(节点o){
如果(距离小于o.distance){
返回-1;
}否则,如果(距离>o.distance){
返回1;
}否则{
返回0;
}
}
@凌驾
公共字符串toString(){
返回“键=”+键+”距离=+距离;
}
@凌驾
公共int hashCode(){
返回键;
}
@凌驾
公共布尔等于(对象obj){
if(this==obj){
返回true;
}
如果(!(节点的obj实例)){
返回false;
}
节点其他=(节点)obj;
return key==other.key;
}
}
MinPriorityQueue
private static class Node implements Comparable<Node> {
final int key;
int distance = Integer.MAX_VALUE;
Node prev = null;
public Node(int key) {
this.key = key;
}
@Override
public int compareTo(Node o) {
if (distance < o.distance) {
return -1;
} else if (distance > o.distance) {
return 1;
} else {
return 0;
}
}
@Override
public String toString() {
return "key=" + key + " distance=" + distance;
}
@Override
public int hashCode() {
return key;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Node)) {
return false;
}
Node other = (Node) obj;
return key == other.key;
}
}
public static class MinPriorityQueue {
private Node[] array;
private int heapSize;
public MinPriorityQueue(Node[] array) {
this.array = array;
this.heapSize = this.array.length;
}
public Node extractMin() {
Node temp = array[0];
swap(0, heapSize - 1, array);
heapSize--;
sink(0);
return temp;
}
public boolean isEmpty() {
return heapSize == 0;
}
public void buildMinHeap() {
for (int i = heapSize / 2 - 1; i >= 0; i--) {
sink(i);
}
}
public void decreaseKey(int index, Node key) {
if (key.compareTo(array[index]) >= 0) {
throw new IllegalArgumentException("the new key must be greater than the current key");
}
array[index] = key;
while (index > 0 && array[index].compareTo(array[parentIndex(index)]) < 0) {
swap(index, parentIndex(index), array);
index = parentIndex(index);
}
}
private int parentIndex(int index) {
return (index - 1) / 2;
}
private int left(int index) {
return 2 * index + 1;
}
private int right(int index) {
return 2 * index + 2;
}
private void sink(int index) {
int smallestIndex = index;
int left = left(index);
int right = right(index);
if (left < heapSize && array[left].compareTo(array[smallestIndex]) < 0) {
smallestIndex = left;
}
if (right < heapSize && array[right].compareTo(array[smallestIndex]) < 0) {
smallestIndex = right;
}
if (index != smallestIndex) {
swap(smallestIndex, index, array);
sink(smallestIndex);
}
}
public Node min() {
return array[0];
}
private void swap(int i, int j, Node[] array) {
Node temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
公共静态类MinPriorityQueue{
私有节点[]数组;
私人治疗;
公共最小优先级队列(节点[]数组){
this.array=数组;
this.heapSize=this.array.length;
}
公共节点extractMin(){
节点温度=数组[0];
交换(0,治疗-1,阵列);
医治--;
水槽(0);
返回温度;
}
公共布尔值为空(){
返回heapSize==0;
}
公共void buildMinHeap(){
对于(inti=heapSize/2-1;i>=0;i--){
水槽(一);
}
}
public void decreaseKey(int索引,节点键){
if(key.compareTo(数组[索引])>=0){
抛出新的IllegalArgumentException(“新密钥必须大于当前密钥”);
}
数组[索引]=键;
while(index>0&&array[index]。比较(array[parentIndex(index)])<0){
交换(索引、父索引(索引)、数组);
索引=父索引(索引);
}
}
私有整数父索引(整数索引){
收益率(指数-1)/2;
}
私有整数左(整数索引){
返回2*index+1;
}
私有整数权限(整数索引){
返回2*index+2;
}
专用void接收器(int索引){
int smallestIndex=索引;
int left=左(索引);
int right=right(索引);
if(left
假设图形由顶点(节点)组成,在本例中,有7(0->6)个顶点和边。这些由以下模型表示:
节点型号:
public class Vertex{
final private String id;
final private String name;
public Vertex(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Vertex other = (Vertex) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public String toString() {
return name;
}
}
public class Edge {
private final String id;
private final Vertex source;
private final Vertex destination;
private final int weight;
public Edge(String id, Vertex source, Vertex destination, int weight) {
this.id = id;
this.source = source;
this.destination = destination;
this.weight = weight;
}
public String getId() {
return id;
}
public Vertex getDestination() {
return destination;
}
public Vertex getSource() {
return source;
}
public int getWeight() {
return weight;
}
@Override
public String toString() {
return source + " " + destination;
}
}
此模型将显示边缘:边缘
public class Vertex{
final private String id;
final private String name;
public Vertex(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Vertex other = (Vertex) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public String toString() {
return name;
}
}
public class Edge {
private final String id;
private final Vertex source;
private final Vertex destination;
private final int weight;
public Edge(String id, Vertex source, Vertex destination, int weight) {
this.id = id;
this.source = source;
this.destination = destination;
this.weight = weight;
}
public String getId() {
return id;
}
public Vertex getDestination() {
return destination;
}
public Vertex getSource() {
return source;
}
public int getWeight() {
return weight;
}
@Override
public String toString() {
return source + " " + destination;
}
}
此类将显示图形(节点+边):graph
public class Graph {
private final List<Vertex> vertexes;
private final List<Edge> edges;
public Graph(List<Vertex> vertexes, List<Edge> edges) {
this.vertexes = vertexes;
this.edges = edges;
}
public List<Vertex> getVertexes() {
return vertexes;
}
public List<Edge> getEdges() {
return edges;
}
}
公共类图{
私有最终列表顶点;
私人最终名单边缘;
公共图(列出顶点、列出边){
this.vertexs=顶点;
这个。边=边;
}
公共列表getVertex(){
返回顶点;
}
公共列表getEdge(){
返回边;
}
}
这是Dijkstra算法的一个简单实现。它不使用任何性能优化:
public class DijkstraAlgorithm {
private final List<Vertex> nodes;
private final List<Edge> edges;
private Set<Vertex> settledNodes;
private Set<Vertex> unSettledNodes;
private Map<Vertex, Vertex> predecessors;
private Map<Vertex, Integer> distance;
public DijkstraAlgorithm(Graph graph) {
// create a copy of the array so that we can operate on this array
this.nodes = new ArrayList<Vertex>(graph.getVertexes());
this.edges = new ArrayList<Edge>(graph.getEdges());
}
public void execute(Vertex source) {
settledNodes = new HashSet<Vertex>();
unSettledNodes = new HashSet<Vertex>();
distance = new HashMap<Vertex, Integer>();
predecessors = new HashMap<Vertex, Vertex>();
distance.put(source, 0);
unSettledNodes.add(source);
while (unSettledNodes.size() > 0) {
Vertex node = getMinimum(unSettledNodes);
settledNodes.add(node);
unSettledNodes.remove(node);
findMinimalDistances(node);
}
}
private void findMinimalDistances(Vertex node) {
List<Vertex> adjacentNodes = getNeighbors(node);
for (Vertex target : adjacentNodes) {
if (getShortestDistance(target) > getShortestDistance(node)
+ getDistance(node, target)) {
distance.put(target, getShortestDistance(node)
+ getDistance(node, target));
predecessors.put(target, node);
unSettledNodes.add(target);
}
}
}
private int getDistance(Vertex node, Vertex target) {
for (Edge edge : edges) {
if (edge.getSource().equals(node)
&& edge.getDestination().equals(target)) {
return edge.getWeight();
}
}
throw new RuntimeException("Should not happen");
}
private List<Vertex> getNeighbors(Vertex node) {
List<Vertex> neighbors = new ArrayList<Vertex>();
for (Edge edge : edges) {
if (edge.getSource().equals(node)
&& !isSettled(edge.getDestination())) {
neighbors.add(edge.getDestination());
}
}
return neighbors;
}
private Vertex getMinimum(Set<Vertex> vertexes) {
Vertex minimum = null;
for (Vertex vertex : vertexes) {
if (minimum == null) {
minimum = vertex;
} else {
if (getShortestDistance(vertex) < getShortestDistance(minimum)) {
minimum = vertex;
}
}
}
return minimum;
}
private boolean isSettled(Vertex vertex) {
return settledNodes.contains(vertex);
}
private int getShortestDistance(Vertex destination) {
Integer d = distance.get(destination);
if (d == null) {
return Integer.MAX_VALUE;
} else {
return d;
}
}
/*
* This method returns the path from the source to the selected target and
* NULL if no path exists
*/
public LinkedList<Vertex> getPath(Vertex target) {
LinkedList<Vertex> path = new LinkedList<Vertex>();
Vertex step = target;
// check if a path exists
if (predecessors.get(step) == null) {
return null;
}
path.add(step);
while (predecessors.get(step) != null) {
step = predecessors.get(step);
path.add(step);
}
// Put it into the correct order
Collections.reverse(path);
return path;
}
}
公共类dijkstra算法{
私有最终列表节点;
私人最终名单边缘;
私有集合结算节点;
私有集未结算节点;
私有地图;
私有地图距离;
公共Dijkstra算法(图){
//创建阵列的副本,以便我们可以在此阵列上操作
this.nodes=newArrayList(graph.getVertexs());
this.edges=newarraylist(graph.getEdges());
}
公共void执行(顶点源){
settledNodes=新HashSet();
unsetledNodes=新HashSet();
距离=新HashMap();
前辈=新的HashMap();
距离。放置(源,0);
未设置的数据节点。添加(源);
while(unsetledNodes.size()>0){
顶点节点=getMinimum(未设置的节点);
结算节点。添加(节点);
未设置的节点。删除(节点);
findminimaldistance(节点);
}
}
私有无效findMinimalDi