Priority queue: strange behaviour
I'm implementing this priority queue to be used with an implementation of the dijkstra algorithm:
Code:
package structures;
public class PriorityQueue {
private Node[] elements;
private int lastIndex;
/**
* Creation of an empty Pq
* @param n
*/
public PriorityQueue(int n) {
this.elements = new Node[n+1];
lastIndex = 0;
}
/**
* Determine if the heap is empty
* @return true if the heap is empty, false if not
*/
public boolean isEmpty() {
return lastIndex == 0;
}
/**
* Inserts an element into heap
* @param n
* @param d
*/
public void add(Node n, double d) {
n.setDistance(d);
elements[++lastIndex] = n;
n.setHeapIndex(lastIndex);
moveUp(lastIndex);
//FIXME setFathers();
}
/**
* Returns (and deletes) the node with minimum priority
* @return minumum priority node
*/
public Node deleteMin() {
if(lastIndex == 0)
throw new IllegalArgumentException();
Node min = elements[1];
if(lastIndex == 1)
lastIndex = 0;
else {
elements[1] = elements[lastIndex--];
elements[1].setHeapIndex(1);
moveDown(1);
//FIXME setFathers();
}
return min;
}
/**
* changes in u the priority of the node u
* and ensure the correct position of the node
* @param u
* @param d
*/
public void changePriority(Node u, double d) {
if(u.getHeapIndex() > lastIndex)
throw new IllegalArgumentException();
double oldDist = u.getDistance();
elements[u.getHeapIndex()].setDistance(d);
elements[u.getHeapIndex()].setFather(u.getFather());
if (!u.getName().equals(elements[u.getHeapIndex()].getName()))
System.err.println("I should change the priority of : " + u.getName()+", instead I'm changin to: " + elements[u.getHeapIndex()].getName());
if(d > oldDist)
moveDown(u.getHeapIndex());
else if(d < oldDist)
moveUp(u.getHeapIndex());
//FIXME setFathers();
}
/**
* moveup
* @param i
*/
private void moveUp(int i) {
if(i > lastIndex)
throw new IllegalArgumentException();
Node elem = elements[i];
while(i > 1 && elem.getDistance() < elements[i/2].getDistance()) {
elements[i] = elements[i/2];
elements[i].setHeapIndex(i);
i = i/2;
}
elements[i] = elem;
elements[i].setHeapIndex(i);
}
/**
* Movedown
* @param i
*/
private void moveDown(int i) {
if(i > lastIndex)
throw new IllegalArgumentException();
Node elem = elements[i];
int j;
while((j = 2*i) <= lastIndex) {
if(j+1 <= lastIndex && elements[j+1].getDistance() < elements[j].getDistance())
j++;
if(elem.getDistance() <= elements[j].getDistance())
break;
elements[i] = elements[j];
elements[i].setHeapIndex(i);
i = j;
}
elements[i] = elem;
elements[i].setHeapIndex(i);
}
/**
* Unused
*/
@SuppressWarnings("unused")
private void setFathers() {
for(int i = 1; i <= lastIndex; i++) {
if(i == 1)
elements[i].setFather(null);
else
elements[i].setFather(elements[i/2]);
}
}
/**
* Prints the heap by levels
*/
public void printHeap() {
int level = 1;
System.out.println("HEAP");
for(int i = 1; i <= lastIndex; i++) {
if(i == 1) {
System.out.println(" " + elements[i].getName() + "(" + elements[i].getDistance() + "::" + elements[i].getHeapIndex() + "::" + elements[i].getFather() + ")");
level++;
}
else if(i < Math.pow(2, level))
System.out.print(" " + elements[i].getName() + "(" + elements[i].getDistance() + "::" + elements[i].getHeapIndex() + "::" + elements[i].getFather() + ")");
else {
System.out.println();
System.out.print(" " + elements[i].getName() + "(" + elements[i].getDistance() + "::" + elements[i].getHeapIndex() + "::" + elements[i].getFather() + ")");
level++;
}
}
System.out.println();
System.out.println("END HEAP");
}
/**
* returns the node of that index
* @param heapIndex
* @return nodo di indice heapIndex nello heap
*/
public Node getNode(int heapIndex) {
return elements[heapIndex];
}
}
it works pretty well, but strange things happens with the last element I change the priority in dikstra (btw, this is the code)
Code:
package algorithm;
import java.io.FileOutputStream;
import java.io.PrintStream;
import auxiliary.Nodes;
import structures.Arc;
import structures.Graph;
import structures.Node;
import structures.PriorityQueue;
public class Dijkstra {
public static Nodes shortestPaths(Node s) {
Nodes ns = new Nodes();
FileOutputStream fos;
PrintStream file = null;
try {
fos = new FileOutputStream("output/ourOutput.txt");
file = new PrintStream(fos);
} catch(Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Node workingNode = new Node();
PriorityQueue pq = new PriorityQueue(Graph.getInstance().nodes().size());
for(Node n : Graph.getInstance().nodes()) {
if(n.getName().equals(s.getName()))
pq.add(n, 0);
else
pq.add(n, Double.POSITIVE_INFINITY);
}
pq.printHeap();
while(!pq.isEmpty()) {
workingNode = pq.deleteMin();
ns.add(workingNode);
//pq.printHeap();
file.println("now WorkingNode is: " + workingNode.getName());
for(Arc a : workingNode.getArcs()) {
file.println(
"Processing Arc: " + a +" Distance are: " + workingNode.getName() +
": "+ workingNode.getDistance() + " + " + a.getWeight() + " = " +
(workingNode.getDistance() + a.getWeight()) + " -> " +
a.getTarget().getName() + ": " + a.getTarget().getDistance()
);
if(workingNode.getDistance()+a.getWeight() < a.getTarget().getDistance()) {
a.getTarget().setFather(workingNode);
System.err.println("ho settato il padre di "+ a.getTarget().getName()+ " a " + workingNode.getName());
a.getTarget().setDistance(workingNode.getDistance()+a.getWeight());
file.println("Distance change: "+ a.getTarget().getName() + " now is " + a.getTarget().getDistance());
pq.changePriority(a.getTarget(), a.getTarget().getDistance());
}
}
}
return ns;
}
}
It gives array out of boundary or it changes the priority to a wrong element
I'm quite sure that somewhere I left a +1 or a -1 but I cannot find it (like usually happens in own code...)
I posted in offtopic because I think the problem is too dumb to be posted in "real" java sections :)
thank you in advance if someone wants to help me :(hi):