Displaying the path for Dijkstra algorithm - java

Whats up guys, I have a question regarding the Dijkstra algorithm. I have made it so that a user enter a graph file, and then the user enters the source node and destination node. And my code so far calculates the shortest distance between them, like it's supposed to. However I do not know to print the path of nodes it goes through in order to get to the destination node. Please help this is a homework assignment due today. Here is my code:
package minheap;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class MinHeap {
private int veNum;
private int x;
private int y;
private Vertex[] vertices;
private int size;
public static void main(String[] args) throws FileNotFoundException{
Scanner input = new Scanner(System.in);
System.out.println("%%%%%%Enter the name of the file that contains the graph");
String file = input.nextLine();
MinHeap minHeap = new MinHeap(file);
System.out.println("What city would you like to start from?(Please enter a number "
+ "from 0 to 87574)");
int start = Integer.parseInt(input.nextLine());
System.out.println("What city would you like to get to?(Please enter a number "
+ "from 0 to 87574)");
int end = Integer.parseInt(input.nextLine());
minHeap.findShortestPaths(start, end);
}
public MinHeap(String file) throws FileNotFoundException {
Scanner input = new Scanner(new File(file));
String sizeString = input.next(); //get the size as a string
size = Integer.parseInt(sizeString);
System.out.println("======The size is: " + size);
vertices = new Vertex[size];
// addNodes();
input.next();
/*Now read the vertices*/
for(int i = 0; i < vertices.length; i++){
veNum = Integer.parseInt(input.next());
x = Integer.parseInt(input.next());
y = Integer.parseInt(input.next());
vertices[i] = new Vertex(veNum, x, y);
}
/*Now read the edges */
while(input.hasNext()){
int vertex1 = indexForName(input.next());
int vertex2 = indexForName(input.next());
//System.out.println("====" + vertex1 + "====" + vertex2);
/*Formula to calculate the distance(weight)*/
int distance = (int) Math.sqrt(Math.pow(vertices[vertex1].xCord - vertices[vertex2].xCord, 2)
+ Math.pow(vertices[vertex1].yCord - vertices[vertex2].yCord, 2));
/*Pass the 2 vertexes that make an edge, and their distance to addEdge method*/
addEdge(vertex1, vertex2, distance);
/*System.out.println("X cord: " + vertices[vertex1].xCord + "| Y cord: " + vertices[vertex1].yCord +
"| X cord2: " + vertices[vertex2].xCord + "| Y cord2: " + vertices[vertex2].yCord);
*/
}
}
//======================================================================================================
int indexForName(String name){
for(int i = 0; i < vertices.length; i++){
/*Look for the vertex name in the array to see if they match with the one the one from
the file */
if(vertices[i].name == Integer.parseInt(name)){
return i;
}
}
return -1;
}
//===============================================================================================================
public void addEdge(int sourceName, int destinationName, int weight) {
int srcIndex = sourceName;
int destiIndex = destinationName;
vertices[srcIndex].adj = new Neighbour(destiIndex, weight, vertices[srcIndex].adj);
vertices[destiIndex].indegree++;
}
public void findShortestPaths(int sourceName, int end){
for (int i = 0; i < size; i++) {
if (vertices[i].name == sourceName) {
applyDikjstraAlgorith(vertices[i], vertices[end]);
break;// in this case we need not traverse the nodes which are
// not reachable from the source Node
}
}
//applyDikjstraAlgorith(vertices[sourceName], vertices[end]);
// for(int i = 0; i < size; i++){
// System.out.println("Distance of "+vertices[i].name+" from Source: "+ vertices[i].cost);
//}
}
public class Vertex {
int cost;
int name;
Neighbour adj;
int indegree;
State state;
int xCord;
int yCord;
public Vertex(int name, int xCord, int yCord) {
this.name = name;
cost = Integer.MAX_VALUE;
state = State.NEW;
this.xCord = xCord;
this.yCord = yCord;
}
public int compareTo(Vertex v) {
if (this.cost == v.cost) {
return 0;
}
if (this.cost < v.cost) {
return -1;
}
return 1;
}
}
public enum State {
NEW, IN_Q, VISITED
}
public class Neighbour {
int index;
Neighbour next;
int weight;
Neighbour(int index, int weight, Neighbour next) {
this.index = index;
this.next = next;
this.weight = weight;
}
}
public void applyDikjstraAlgorith(Vertex src, Vertex end) {
Heap heap = new Heap(size);
heap.add(src);
src.state = State.IN_Q;
src.cost = 0;
while (!heap.isEmpty()) {
Vertex u = heap.remove();
u.state = State.VISITED;
Neighbour temp = u.adj; //the neighbor of the vertex being removed. it accesses it adj neighbor list
System.out.println("=======Edge weights");
while (temp != null) { //while it has a neighbor
if (vertices[temp.index].state == State.NEW) { //if that neighbor is unvisited
heap.add(vertices[temp.index]); //add the unvisited vertices to the heap
vertices[temp.index].state = State.IN_Q; //make the state indicating its in the heap
}
System.out.println("Weight from "+ vertices[u.name].name + " to " + vertices[temp.index].name +" is "+ temp.weight);
if (vertices[temp.index].cost > u.cost + temp.weight) { //if the neighbors weight is less than
vertices[temp.index].cost = u.cost + temp.weight;
heap.heapifyUP(vertices[temp.index]);
}
temp = temp.next;
}
}
System.out.println();
System.out.println("The shortest distance from "+src.name +" to "+end.name+" is "
+ end.cost);
}
public static class Heap {
private Vertex[] heap;
private int maxSize;
private int size; //starts off as 0
public Heap(int maxSize) {
this.maxSize = maxSize;
heap = new Vertex[maxSize]; //make the max size for the heap array made of vertices
}
public void add(Vertex u) {
heap[size++] = u; //fill the heap array with the vertices, starting at position 0
//
heapifyUP(size - 1); //pass each vertext ino heapifyUP (vertex type)
}
public void heapifyUP(Vertex u) {
for (int i = 0; i < maxSize; i++) { //look for vertex in the heap array
if (u == heap[i]) {
heapifyUP(i); //if its found, go to heapifyUp method (int type) and pass in the vertex num
break;
}
}
}
public void heapifyUP(int position) {
int currentIndex = position;
Vertex currentItem = heap[currentIndex];
int parentIndex = (currentIndex - 1) / 2;
Vertex parentItem = heap[parentIndex];
while (currentItem.compareTo(parentItem) == -1) {
swap(currentIndex, parentIndex);
currentIndex = parentIndex;
if (currentIndex == 0) {
break;
}
currentItem = heap[currentIndex];
parentIndex = (currentIndex - 1) / 2;
parentItem = heap[parentIndex];
}
}
public Vertex remove() {
Vertex v = heap[0];
swap(0, size - 1);
heap[size - 1] = null;
size--;
heapifyDown(0);
return v;
}
public void heapifyDown(int postion) {
if (size == 1) {
return;
}
int currentIndex = postion;
Vertex currentItem = heap[currentIndex];
int leftChildIndex = 2 * currentIndex + 1;
int rightChildIndex = 2 * currentIndex + 2;
int childIndex;
if (heap[leftChildIndex] == null) {
return;
}
if (heap[rightChildIndex] == null) {
childIndex = leftChildIndex;
} else if (heap[rightChildIndex].compareTo(heap[leftChildIndex]) == -1) {
childIndex = rightChildIndex;
} else {
childIndex = leftChildIndex;
}
Vertex childItem = heap[childIndex];
while (currentItem.compareTo(childItem) == 1) {
swap(currentIndex, childIndex);
currentIndex = childIndex;
currentItem = heap[currentIndex];
leftChildIndex = 2 * currentIndex + 1;
rightChildIndex = 2 * currentIndex + 2;
if (heap[leftChildIndex] == null) {
return;
}
if (heap[rightChildIndex] == null) {
childIndex = leftChildIndex;
} else if (heap[rightChildIndex].compareTo(heap[leftChildIndex]) == -1) {
childIndex = rightChildIndex;
} else {
childIndex = leftChildIndex;
}
}
}
public void swap(int index1, int index2) {
Vertex temp = heap[index1];
heap[index1] = heap[index2];
heap[index2] = temp;
}
public boolean isEmpty() {
return size == 0;
}
}
}
The sample.txt file is as follows:
6 9
0 1000 2400
1 2800 3000
2 2400 2500
3 4000 0
4 4500 3800
5 6000 1500
0 1
0 3
1 2
1 4
2 4
2 3
2 5
3 5
Again, the actual algorithm works, I just need help printing the path. Thanks in advance

Related

Dijkstras algorithm shortest path in directed graph, find the last node taken to destination vertex

The code below was taken from https://algorithms.tutorialhorizon.com/dijkstras-shortest-path-algorithm-spt-adjacency-list-and-min-heap-java-implementation/
it finds the shortest distance to each vertex from a given source vertex but does not as of yet offer a way to track the path taken. Is there an easy fix to this? if not how should i approach this?
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.StringTokenizer;
public class DijkstraMinHeap {
static class Edge {
int source;
int destination;
int weight;
public Edge(int source, int destination, int weight) {
this.source = source;
this.destination = destination;
this.weight = weight;
}
}
static class HeapNode{
int vertex;
int distance;
}
static class Graph {
int vertices;
LinkedList<Edge>[] adjacencylist;
Graph(int vertices) {
this.vertices = vertices;
adjacencylist = new LinkedList[vertices];
for (int i = 0; i <vertices ; i++) {
adjacencylist[i] = new LinkedList<>();
}
}
public void addEdge(int source, int destination, int weight) {
Edge edge = new Edge(source, destination, weight);
adjacencylist[source].addFirst(edge);
/**edge = new Edge(destination, source, weight);
adjacencylist[destination].addFirst(edge); //for undirected graph*/
}
public void dijkstra_GetMinDistances(int sourceVertex){
int INFINITY = Integer.MAX_VALUE;
boolean[] SPT = new boolean[vertices];
// //create heapNode for all the vertices
HeapNode [] heapNodes = new HeapNode[vertices];
for (int i = 0; i <vertices ; i++) {
heapNodes[i] = new HeapNode();
heapNodes[i].vertex = i;
heapNodes[i].distance = INFINITY;
}
//decrease the distance for the first index
heapNodes[sourceVertex].distance = 0;
//add all the vertices to the DijkstraMinHeap.MinHeap
MinHeap minHeap = new MinHeap(vertices);
for (int i = 0; i <vertices ; i++) {
minHeap.insert(heapNodes[i]);
}
//while minHeap is not empty
while(!minHeap.isEmpty()){
//extract the min
HeapNode extractedNode = minHeap.extractMin();
//extracted vertex
int extractedVertex = extractedNode.vertex;
SPT[extractedVertex] = true;
//iterate through all the adjacent vertices
LinkedList<Edge> list = adjacencylist[extractedVertex];
for (int i = 0; i <list.size() ; i++) {
Edge edge = list.get(i);
int destination = edge.destination;
//only if destination vertex is not present in SPT
if(SPT[destination]==false ) {
///check if distance needs an update or not
//means check total weight from source to vertex_V is less than
//the current distance value, if yes then update the distance
int newKey = heapNodes[extractedVertex].distance + edge.weight ;
int currentKey = heapNodes[destination].distance;
if(currentKey>newKey){
decreaseKey(minHeap, newKey, destination);
heapNodes[destination].distance = newKey;
}
}
}
}
//print SPT
printDijkstra(heapNodes, sourceVertex);
}
public void decreaseKey(MinHeap minHeap, int newKey, int vertex){
//get the index which distance's needs a decrease;
int index = minHeap.indexes[vertex];
//get the node and update its value
HeapNode node = minHeap.mH[index];
node.distance = newKey;
minHeap.bubbleUp(index);
}
public void printDijkstra(HeapNode[] resultSet, int sourceVertex){
System.out.println("Dijkstra's Algorithm: (using Adjacency List and Min Heap)");
for (int i = 0; i <vertices ; i++) {
String x = String.valueOf(resultSet[i].distance);
if(resultSet[i].distance == Integer.MAX_VALUE){
x = "unreachable";
}
System.out.println("Node: " + i + " | predecessor " + resultSet[i].vertex+
" | distance: " + x);
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("./vg1.txt"));
printResult(br);
}
public static void printResult(BufferedReader br) throws IOException {
StringTokenizer st = new StringTokenizer((br.readLine()));
int vertices = Integer.parseInt(st.nextToken());
Graph graph = new Graph(vertices);
int K = Integer.parseInt((st.nextToken()));
for (int i = 0; i < K; i++) {
st = new StringTokenizer(br.readLine());
int from = Integer.parseInt(st.nextToken());
int to = Integer.parseInt(st.nextToken());
int weight = Integer.parseInt(st.nextToken());
graph.addEdge(from, to, weight);
}
int source_vertex = 1;
graph.dijkstra_GetMinDistances(source_vertex);
}
static class MinHeap {
int capacity;
int currentSize;
HeapNode[] mH;
int[] indexes; //will be used to decrease the distance
public MinHeap(int capacity) {
this.capacity = capacity;
mH = new HeapNode[capacity + 1];
indexes = new int[capacity];
mH[0] = new HeapNode();
mH[0].distance = Integer.MIN_VALUE;
mH[0].vertex = -1;
currentSize = 0;
}
public void display() {
for (int i = 0; i <= currentSize; i++) {
System.out.println(" " + mH[i].vertex + " distance " + mH[i].distance);
}
System.out.println("________________________");
}
public void insert(HeapNode x) {
currentSize++;
int idx = currentSize;
mH[idx] = x;
indexes[x.vertex] = idx;
bubbleUp(idx);
}
public void bubbleUp(int pos) {
int parentIdx = pos / 2;
int currentIdx = pos;
while (currentIdx > 0 && mH[parentIdx].distance > mH[currentIdx].distance) {
HeapNode currentNode = mH[currentIdx];
HeapNode parentNode = mH[parentIdx];
//swap the positions
indexes[currentNode.vertex] = parentIdx;
indexes[parentNode.vertex] = currentIdx;
swap(currentIdx, parentIdx);
currentIdx = parentIdx;
parentIdx = parentIdx / 2;
}
}
public HeapNode extractMin() {
HeapNode min = mH[1];
HeapNode lastNode = mH[currentSize];
// update the indexes[] and move the last node to the top
indexes[lastNode.vertex] = 1;
mH[1] = lastNode;
mH[currentSize] = null;
sinkDown(1);
currentSize--;
return min;
}
public void sinkDown(int k) {
int smallest = k;
int leftChildIdx = 2 * k;
int rightChildIdx = 2 * k + 1;
if (leftChildIdx < heapSize() && mH[smallest].distance > mH[leftChildIdx].distance) {
smallest = leftChildIdx;
}
if (rightChildIdx < heapSize() && mH[smallest].distance > mH[rightChildIdx].distance) {
smallest = rightChildIdx;
}
if (smallest != k) {
HeapNode smallestNode = mH[smallest];
HeapNode kNode = mH[k];
//swap the positions
indexes[smallestNode.vertex] = k;
indexes[kNode.vertex] = smallest;
swap(k, smallest);
sinkDown(smallest);
}
}
public void swap(int a, int b) {
HeapNode temp = mH[a];
mH[a] = mH[b];
mH[b] = temp;
}
public boolean isEmpty() {
return currentSize == 0;
}
public int heapSize() {
return currentSize;
}
}
}
Try to add the Edge[] edgeTo array that will track the the edge that you used to reach specific vertex.
For example
edgeTo[0] = null
edgeTo[1] = Edge( 0 -> 1 )
edgeto[2] = Edge( 1 -> 2 )
There is the path 0 -> 1 -> 2 and you can find it by traversing backwards.
You can create such an array structure by changing the lines:
public void dijkstra_GetMinDistances(int sourceVertex){
int INFINITY = Integer.MAX_VALUE;
boolean[] SPT = new boolean[vertices];
Edge[] edgeTo = new Edge[vertices];
...
and you will update this edgeTo array in if statement where you find the shorter distance:
if(currentKey>newKey){
edgeTo[destination] = edge;
decreaseKey(minHeap, newKey, destination);
heapNodes[destination].distance = newKey;
}
Finally the method that return the shortest part from source_vertex to any_other_vertex is:
public List<Edge> pathTo(int vertex) {
List<Edge> path = new LinkedList<>();
for (Edge e = edgeTo[vertex]; e != null; e = edgeTo[e.source]) {
path.addFirst(e);
}
return path;
}
All credits goes to great book and online course https://algs4.cs.princeton.edu/home/

How can I build a max heap java class for an object?

I am trying to build a max heap java class for item objects, so I can solve the knapsack problem and implement greedy algorithms to do so. Item class includes weight, value, Id(to distinguish items), and most importantly a priority factor:
public class Items {
double weight;
double value;
double priorityFactor;
int ID;
//constructor for items class
public Items(int weight, int value, int id, int priorityFactor)
{
this.weight=weight;
this.value=value;
this.ID=id;
this.priorityFactor = priorityFactor;
} //end constructor
Now the issue that I'm facing is in the max heap class, which is supposed to build me a max heap tree based on the priority factor. Means that I should have an array of item objects: private Items[] array
What I'm finding difficult to implement is how can I insert those items in the array based on the priority factor. If I do this, I think I will be able to implement the greedy algorithms. How to handle this?
This is the basic code for a min/max heap (depending on the T:compareTo() method).
This only handles insertion, but I think it's what you're after.
package jc.lib.container.collection.set;
import jc.lib.lang.string.JcStringBuilder;
public class JcHeap<T extends Comparable<T>> {
private T[] mItems;
private int mItemCount = 0;
#SuppressWarnings("unchecked") public JcHeap(final int pStartCapacity) {
mItems = (T[]) new Comparable[pStartCapacity];
}
private void checkResize() {
if (mItems.length <= mItemCount) {
final int newSize = (mItems.length) * 2;
#SuppressWarnings("unchecked") final T[] tmp = (T[]) new Comparable[newSize];
if (mItems != null) System.arraycopy(mItems, 0, tmp, 0, mItemCount);
mItems = tmp;
}
}
static private int getParentIndex(final int pCurrentIndex) {
return (pCurrentIndex - 1) / 2;
}
#SuppressWarnings("unused") static private int getLeftChildIndex(final int pCurrentIndex) {
return 2 * pCurrentIndex + 1;
}
#SuppressWarnings("unused") static private int getRightChildIndex(final int pCurrentIndex) {
return 2 * pCurrentIndex + 2;
}
public void addItem(final T pItem) {
checkResize();
// insert
System.out.println("\nInserting " + pItem);
T current = pItem;
int currentIndex = mItemCount;
mItems[currentIndex] = current;
++mItemCount;
// sort
while (true) { // swap up
if (currentIndex <= 0) break;
final int parentIndex = getParentIndex(currentIndex);
final T parent = mItems[parentIndex];
System.out.print("Checking cur:" + current + " vs par:" + parent + " => " + current.compareTo(parent) + "/");
if (current.compareTo(parent) >= 0) {
System.out.println("break");
break;
}
System.out.println("swap");
System.out.println("Swapping with parent: " + parent);
final T tmp = mItems[parentIndex];
mItems[parentIndex] = mItems[currentIndex];
mItems[currentIndex] = tmp;
currentIndex = parentIndex;
current = mItems[currentIndex];
}
}
// public boolean contains(final T pItem) {
// final int index = findIndex(pItem);
// return 0 <= index && index < mItemCount;
// }
//
// public int findIndex(final T pItem) {
// int index = 0;
// int width = mItemCount;
//
// while (true) {
// System.out.println("Comparing with index " + index);
// final int cmp = pItem.compareTo(mItems[index]);
// if (cmp == 0) return index;
// else if (cmp > 0) return -1;
//
// index += mItemCount;
// width /= 2;
// if (width == 0) return -1;
// }
// }
#Override public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("\nTree View:\n");
int height = (int) (Math.log(mItemCount) / Math.log(2));
sb.append("count=" + mItemCount + " height=" + height);
int next = 1;
sb.append("\n[");
sb.append(JcStringBuilder.buildFromArray(", ", (Object[]) mItems));
// for (int c = 0; c < mItemCount; c++) {
// sb.append("\n" + mItems);
// }
sb.append("]");
for (int c = 0; c < mItemCount; c++) {
if (c + 2 > next) {
sb.append("\n");
for (int d = 0; d < height; d++) {
sb.append("\t");
}
height -= 1;
next *= 2;
// System.out.println("Next is " + next);
}
sb.append("<" + mItems[c] + ">\t");
}
return sb.toString() + "\n";
}
}

How do I stop this loop from changing the value?

I'm trying to implement a heapsort on an array of objects which has already been created. It is meant to be sorted according to their eventTime attribute, yet each eventTime attribute is set to the same as the others by the time the queue is sorted. Is there any way to fix this so that it creates a 'priorityqueue' in ascending order?
Main:
public static void main(String[] args) {
CustomerQueue cQ = new CustomerQueue(0, 0, false);
for (int i = 0; i < 10; i++) {
CustomerQueue cQ1 = new CustomerQueue(0, 0, false);
cQ.enqueue(cQ1);
System.out.println(cQ1.arrivalTime);
}
System.out.print("\n");
PriorityQueue pQ = new PriorityQueue(0, 0, 0, false);
while (!cQ.isEmpty()) {
for (CustomerQueue c : cQ.array) {
PriorityQueue pQ1 = new PriorityQueue(0, 0, 0, false);
pQ1.eventTime = c.arrivalTime;
pQ.enqueue(pQ1);
System.out.println(pQ1.eventTime);
cQ.dequeue();
}
}
pQ.sort(pQ.array);
System.out.println(Arrays.toString(pQ.array));
}
PriorityQueue:
class PriorityQueue {
PriorityQueue array[] = new PriorityQueue[10];
private int front;
private int rear;
private int count;
private int eventType;
double eventTime;
private double tallyTime;
private boolean paymentMethod;
public PriorityQueue(int evT, int eT, double tT, boolean pM) {
this.eventType = evT;
this.eventTime = eT;
this.tallyTime = tT;
this.paymentMethod = pM;
front = 0;
rear = -1;
count = 0;
}
public void enqueue(PriorityQueue pQ) {
if (isFull()) {
System.out.println("OverFlow\nProgram Terminated");
System.exit(1);
}
rear = (rear + 1);
array[rear] = pQ;
count++;
}
public void sort(PriorityQueue arr[]) {
int n = arr.length;
// Build heap (rearrange array)
for (int i = n / 2 - 1; i >= 0; i--) {
heapify(arr, n, i);
}
// One by one extract an element from heap
for (int i = n - 1; i >= 0; i--) {
// Move current root to end
int temp = (int) arr[0].eventTime;
arr[0] = arr[i];
arr[i].eventTime = temp;
// call max heapify on the reduced heap
heapify(arr, i, 0);
}
}
void heapify(PriorityQueue arr[], int n, int i) {
int largest = i; // Initialize largest as root
int l = 2 * i + 1; // left = 2*i + 1
int r = 2 * i + 2; // right = 2*i + 2
// If left child is larger than root
if (l < n && arr[l].eventTime > arr[largest].eventTime) {
largest = l;
}
// If right child is larger than largest so far
if (r < n && arr[r].eventTime > arr[largest].eventTime) {
largest = r;
}
// If largest is not root
if (largest != i) {
int swap = (int) arr[i].eventTime;
arr[i] = arr[largest];
arr[largest].eventTime = swap;
// Recursively heapify the affected sub-tree
heapify(arr, n, largest);
}
}
public void dequeue() {
if (isEmpty()) {
System.out.println("UnderFlow\nProgram Terminated");
System.exit(1);
}
front = (front + 1) % array.length;
count--;
}
public boolean isEmpty() {
return (size() == 0);
}
public int size() {
return count;
}
public boolean isFull() {
return (size() == array.length);
}
public PriorityQueue peek() {
if (isEmpty()) {
System.out.println("UnderFlow\nProgram Terminated");
System.exit(1);
}
return array[front];
}
#Override
public String toString() {
return eventType + " " + eventTime + " " + tallyTime + " " + paymentMethod;
}
}
I see two parts which are most likely wrong and the cause of your issue:
In the heapify method you have:
int swap = (int) arr[i].eventTime;
arr[i] = arr[largest];
arr[largest].eventTime = swap;
And in the sort method you have:
int temp = (int) arr[0].eventTime;
arr[0] = arr[i];
arr[i].eventTime = temp;
Assuming you want to switch the CustomerQueue objects around inside the array, they should be this instead:
// In the heapify:
CustomerQueue swap = arr[i];
arr[i] = arr[largest];
arr[largest] = swap;
// In the sort:
CustomerQueue temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
What your code currently does in pseudo-code is this:
CustomerQueue ith has for example name = "I", eventTime = 1
CustomerQueue largest has for example name = "largest", eventTime = 2
int temp = (int) arr[i].eventTime; // temp is now 1
arr[i] = arr[largest]; // Both arr[i] AND arr[largest] are now CustomerQueue largest (with name = "largest" and eventTime = 2)
arr[i].eventTime = temp; // Both arr[i] AND arr[largest] are now changed to eventTime temp (which is 1)
So now both arr[i] and arr[largest] will hold: name = "largest" and eventTime = 1, as well as referencing the same CustomerQueue-instance.

Building a min heap using java

I tried to build a minHeap using java, this is my code:
public class MyMinHeap {
private ArrayList<Node> heap;
public MyMinHeap() {
heap = new ArrayList<Node>();
}
public MyMinHeap(ArrayList<Node> nodeList) {
heap = nodeList;
buildHeap();
}
public void buildHeap() {
int i = heap.size() / 2;
while (i >= 0) {
minHeapify(i);
i--;
}
}
public Node extractMin() {
if (heap.size() <= 0) return null;
Node minValue = heap.get(0);
heap.set(0, heap.get(heap.size() - 1));
heap.remove(heap.size() - 1);
minHeapify(0);
return minValue;
}
public String toString() {
String s = "";
for (Node n : heap) {
s += n + ",";
}
return s;
}
public void minHeapify(int i) {
int left = 2 * i + 1;
int right = 2 * i + 2;
int smallest = i;
if (left < heap.size() - 1 && lessThan(left, smallest))
smallest = left;
if (right < heap.size() - 1 && lessThan(right, smallest))
smallest = right;
if (smallest != i) {
swap(smallest, i);
minHeapify(smallest);
}
}
private void swap(int i, int j) {
Node t = heap.get(i);
heap.set(i, heap.get(j));
heap.set(j, t);
}
public boolean lessThan(int i, int j) {
return heap.get(i)
.compareTo(heap.get(j)) < 0;
}
public static void main(String[] args) {
char[] chars = {'a', 'b', 'c', 'd', 'e', 'f'};
int[] freqs = {45, 13, 12, 16, 9, 5};
ArrayList<Node> data = new ArrayList<Node>();
for (int i = 0; i < chars.length; i++) {
data.add(new Node(chars[i], freqs[i]));
}
MyMinHeap heap = new MyMinHeap(data);
System.out.println("print the heap : " + heap);
for (int i = 0; i < chars.length; i++) {
System.out.println("Smallest is :" + heap.extractMin());
}
}
}
The output should be:5,9,12,13,16,45,
but what I got is : 9,13,12,16,45
I have debugged this but still can't figure out, anybody help? thanks a lot.
Insert :
When we insert into a min-heap, we always start by inserting the element at the bottom. We insert at the
rightmost spot so as to maintain the complete tree property.
Then, we "fix" the tree by swapping the new element with its parent, until we find an appropriate spot for
the element. We essentially bubble up the minimum element.
This takes 0 (log n) time, where n is the number of nodes in the heap.
Extract Minimum Element :
Finding the minimum element of a min-heap is easy: it's always at the top. The trickier part is how to remove
it. (I n fact, this isn't that tricky.)
First, we remove the minimum element and swap it with the last element in the heap (the bottommost,
rightmost element). Then, we bubble down this element, swapping it with one of its children until the minheap
property is restored.
Do we swap it with the left child or the right child? That depends on their values. There's no inherent
ordering between the left and right element, but you'll need to take the smaller one in order to maintain
the min-heap ordering.
public class MinHeap {
private int[] heap;
private int size;
private static final int FRONT = 1;
public MinHeap(int maxSize) {
heap = new int[maxSize + 1];
size = 0;
}
private int getParent(int position) {
return position / 2;
}
private int getLeftChild(int position) {
return position * 2;
}
private int getRightChild(int position) {
return position * 2 + 1;
}
private void swap(int position1, int position2) {
int temp = heap[position1];
heap[position1] = heap[position2];
heap[position2] = temp;
}
private boolean isLeaf(int position) {
if (position > size / 2) {
return true;
}
return false;
}
public void insert(int data) {
heap[++size] = data;
int currentItemIndex = size;
while (heap[currentItemIndex] < heap[getParent(currentItemIndex)]) {
swap(currentItemIndex, getParent(currentItemIndex));
currentItemIndex = getParent(currentItemIndex);
}
}
public int delete() {
int item = heap[FRONT];
swap(FRONT, size--); // heap[FRONT] = heap[size--];
heapify(FRONT);
return item;
}
private void heapify(int position) {
if (isLeaf(position)) {
return;
}
if (heap[position] > heap[getLeftChild(position)]
|| heap[position] > heap[getRightChild(position)]) {
// if left is smaller than right
if (heap[getLeftChild(position)] < heap[getRightChild(position)]) {
// swap with left
swap(heap[position], heap[getLeftChild(position)]);
heapify(getLeftChild(position));
} else {
// swap with right
swap(heap[position], heap[getRightChild(position)]);
heapify(getRightChild(position));
}
}
}
#Override
public String toString() {
StringBuilder output = new StringBuilder();
for (int i = 1; i <= size / 2; i++) {
output.append("Parent :" + heap[i]);
output
.append("LeftChild : " + heap[getLeftChild(i)] + " RightChild :" + heap[getRightChild(i)])
.append("\n");
}
return output.toString();
}
public static void main(String... arg) {
System.out.println("The Min Heap is ");
MinHeap minHeap = new MinHeap(15);
minHeap.insert(5);
minHeap.insert(3);
minHeap.insert(17);
minHeap.insert(10);
minHeap.insert(84);
minHeap.insert(19);
minHeap.insert(6);
minHeap.insert(22);
minHeap.insert(9);
System.out.println(minHeap.toString());
System.out.println("The Min val is " + minHeap.delete());
}
}
The problem is in your minHeapify function. You have:
public void minHeapify(int i) {
int left = 2 * i + 1;
int right = 2 * i + 2;
int smallest = i;
if (left < heap.size() - 1 && lessThan(left, smallest))
smallest = left;
if (right < heap.size() - 1 && lessThan(right, smallest))
smallest = right;
Now, let's say that your initial array list is {3,2}, and you call minHeapify(0).
left = 2 * i + 1; // = 1
right = 2 * i + 2; // = 2
smallest = i; // 0
Your next statement:
if (left < heap.size() - 1 && lessThan(left, smallest))
At this point, left = 1, and heap.size() returns 2. So left isn't smaller than heap.size() - 1. So your function exits without swapping the two items.
Remove the - 1 from your conditionals, giving:
if (left < heap.size() && lessThan(left, smallest))
smallest = left;
if (right < heap.size() && lessThan(right, smallest))
smallest = right;

Fixing a PathFinding code

I have this path finding code which does the first part of the finding by only going one square
public class PathFinding {
static Vector2 start;
static Vector2 end;
static Cell[][] cells;
static Node currentNode;
static Arena arena;
public static void calcPAth(Vector2 from, Vector2 to,
Cell[][] mapCells, Arena a) {
start = from;
end = to;
cells = mapCells;
arena = a;
List<Node> openList = new ArrayList<Node>();
List<Node> closedList = new ArrayList<Node>();
Gdx.app.log(PArena.LOG, "Lists Created");
currentNode = new Node(null, start);
openList.add(currentNode);
Gdx.app.log(PArena.LOG, "Added start to openList");
// check squares around this and add
int startPX = (int) currentNode.parentV.x / 32;
Gdx.app.log(PArena.LOG, "Start X" + startPX);
int startPY = (int) currentNode.parentV.y / 32;
Gdx.app.log(PArena.LOG, "Start Y" + startPY);
Gdx.app.log("", "");
//
int MIN_X = startPX - 1;
int MIN_Y = startPY - 1;
int MAX_X = startPX + 1;
int MAX_Y = startPY + 1;
int startPosX = (startPX - 1 < MIN_X) ? startPX : startPX - 1;
int startPosY = (startPY - 1 < MIN_Y) ? startPY : startPY - 1;
int endPosX = (startPX + 1 > MAX_X) ? startPX : startPX + 1;
int endPosY = (startPY + 1 > MAX_Y) ? startPY : startPY + 1;
// Check boundaries on start cell
for (int rowNum = startPosX; rowNum <= endPosX; rowNum++) {
for (int colNum = startPosY; colNum <= endPosY; colNum++) {
// All the neighbors will be grid[rowNum][colNum]
if (!cells[rowNum][colNum].getTile().getProperties()
.containsKey("blocked")) {
Node node = new Node(currentNode, new Vector2(
rowNum, colNum));
if (rowNum != startPX && colNum != startPY) {
node.setMovementCost(14);
} else
node.setMovementCost(10);
openList.add(node);
System.out.print(node.getFValue() + "|");
} else
System.out.print("B");
}
System.out.println("");
}
openList.remove(currentNode);
closedList.add(currentNode);
int n = openList.get(0).getFValue();
int index = 0;
for (Node temp : openList) {
if (temp.getFValue() < n) {
n = temp.getFValue();
index = openList.lastIndexOf(temp);
Gdx.app.log("n", "n = " + n);
}
}
currentNode = openList.get(index);
arena.colorSquare(currentNode.getVectorPos());
// need to calc move cost;
//
Gdx.app.log("", "");
openList.clear();
closedList.clear();
}
This is my Node class
public static class Node {
int hVal;
int gVal;
int fVal;
Node parentNode;
Vector2 parentV;
private Node(Node node, Vector2 p) {
setParent(node);
this.parentV = p;
calcHValue();
}
public void setMovementCost(int c) {
this.gVal = c;
calcFVal();
}
private void calcFVal() {
fVal = gVal + hVal;
// Gdx.app.log("Node", "HVal = " + hVal);
// Gdx.app.log("Node", "GVal = " + gVal);
// Gdx.app.log("Node", "FVal = " + fVal);
}
private void calcHValue() {
int x = (int) (parentV.x - end.x);
if (x < 0)
x *= -1;
int y = (int) (parentV.y - end.y);
if (y < 0)
y *= -1;
hVal = (int) (x + y) / 32;
// Gdx.app.log(PArena.LOG, "Heuristic Value" + hVal);
}
private void setParent(Node node) {
this.parentNode = node;
}
public int getFValue() {
return fVal;
}
public Vector2 getVectorPos() {
return parentV;
}
}
My problem is that my debugging outputs like this
15|11|15|
11|11|11|
15|11|15|
So basically it isnt actually calculating the total value. It is just adding the movement cost, not heuristic.
What is th problem? Am i missing a step?
You are missing the Successor list i think. An A* does have a Successorlist and while the openlist isnt empty you do the following stuff:
while (openList.size() != 0) {
successor.clear();
q = openList.remove(); //first element of the prio queue
// generate your neighbornodes of q and add them to the successorlist
//after this you iterate over the successor and check if its your goalnode.
//If so you do return it else you add it to the openlist. (still inside of the while!)
//Dont forget to check if the neighbor is inside of the close list!
//if so you do not need to add it to the successorlist
//Here is how it does look at mine A*. It also contains a check if there is a betterone
// calc
for (Node suc : successor) {
if (suc.x == (int) this.screen.character.mapPos.x
&& suc.y == (int) this.screen.character.mapPos.y)
return suc; //return the goalnode
boolean add = true;
if (betterIn(suc, openList))
add = false;
if (betterIn(suc, closeList))
add = false;
if (add)
openList.add(suc);
}
Last but not least you do delete the q note from the openlist and add it to the close ist.
}
closeList.add(q);
}//end of while
Some more minor improvmements would be that you do add a compareable to the Node..
#Override
public int compareTo(Node o) {
if ((this.g + this.h) < (o.g + o.h))
return -1;
else if ((this.g + this.h) >= (o.g + o.h))
return 1;
else
return 0;
}
also override the equals and the hashCode method for it for example like this:
#Override
public boolean equals(Object o) {
// override for a different compare
return ((Node) o).x == this.x && ((Node) o).y == this.y;
}
#Override
public int hashCode() {
return x + y;
}
After that your openList can be a PriorityQueue<Node> and the first object you are getting from the is always the one with the smallest h.
Dont forget to return our final Node to iterate over the getparent method to get the path.
private boolean betterIn(Node n, Collection<Node> l) {
for (Node no : l) {
if (no.x == n.x && no.y == n.y && (no.g + no.h) <= (n.g + n.h))
return true;
}
return false;
}

Categories

Resources