public class Heap {
GNode[] heapNodes
int size
HashMap<GNode,Integer> nodeIndex
HashMap<GNode,Integer> distances
public class Record{
GNode node
int distance
public Record(GNode node, int distance) {
this.node = node
this.distance = distance
}
}
public Heap(int size) {
heapNodes = new GNode[size]
this.size = size
}
public boolean isEmpty(){
return size==0
}
public boolean isEntered(GNode node){
return nodeIndex.containsKey(node)
}
public boolean isInHeap(GNode node){
return isEntered(node)&&nodeIndex.get(node)!=-1
}
public void addOrUpdateOrIgnore(GNode node , int distance){
if(!isEntered(node)){
heapNodes[size] = node
nodeIndex.put(node,size)
distances.put(node,distance)
heapInsert(node,size)
size++
}
if(isInHeap(node)){
distances.put(node,Math.min(distances.get(node),distance))
heapInsert(node,nodeIndex.get(node))
}
}
public Record pop(){
Record record = new Record(heapNodes[0], distances.get(heapNodes[0]))
swap(0,size-1)
nodeIndex.put(heapNodes[size-1],-1)
distances.remove(heapNodes[size-1])
heapify(heapNodes[0],--size)
return record
}
public void heapInsert(GNode node){
int index = size
this.heapNodes[index] = node
}
public void heapInsert(GNode node,int index){
while (distances.get(node)<distances.get(heapNodes[(index-1)/2])){
swap(index,(index-1)/2)
index = (index-1)/2
}
}
public void heapify(GNode node,int size){
int index = nodeIndex.get(node)
int left = index*2+1
int right = index*2+2
while (left<size){
int smallest = right<size && distances.get(heapNodes[left])<distances.get(heapNodes[right])?left:right
smallest = distances.get(heapNodes[index])<distances.get(heapNodes[smallest])?index:smallest
if(smallest==index) break
swap(smallest,index)
index = smallest
left = index*2+1
right = index*2+2
}
}
public void swap(int x,int y){
nodeIndex.put(heapNodes[x], y)
nodeIndex.put(heapNodes[y],x)
GNode help = heapNodes[x]
heapNodes[x] = heapNodes[y]
heapNodes[y] = help
}
public static HashMap<GNode,Integer> dijkstra(GNode head,int size){
Heap heap = new Heap(size)
HashMap<GNode, Integer> res = new HashMap<>()
heap.addOrUpdateOrIgnore(head,0)
while (!heap.isEmpty()){
Record record = heap.pop()
res.put(record.node,record.distance)
for (Edge edge : record.node.edges) {
heap.addOrUpdateOrIgnore(edge.to,edge.weight+record.distance)
}
}
return res
}
}