implementing Dijkstra's Algorithm using priority queue - java

I'm implementing Dijkstra's Algorithm using priority queue, I want a function to remove an element from the heap but I can only send it the vertex index from the Dijkstra's main and I can't find its position on the heap and I can't afford to do a binary search. Any ideas?
public class MinHeap {
Vertex[] Heap = null; // Vertex array
int Lenght;
int Size;
int[] elementsPostion; // Array of Index of Vertices
private int parent(int i) {
if (i % 2 == 0)
return (i / 2) - 1;
else
return i / 2;
}
private int leftChild(int i) {
return (2 * i) + 1;
}
private int rightChild(int i) {
return (2 * i) + 2;
}
// Initialize PQ
public MinHeap(int len) {
Lenght = len;
Size = 0;
Heap = new Vertex[Lenght];
elementsPostion = new int[Lenght];
}
// Extract Min
public Vertex ExtractMin() {
Vertex v;
v = Heap[0]; // min = index of min
elementsPostion[Heap[0].index] = -1;
Heap[0] = Heap[Size - 1];
elementsPostion[Heap[0].index] = 0;
Size = Size - 1;
minHeapify(0);
return v;
}
// ----------------------------
// Sort Inside PQ
public void minHeapify(int pos) {
int L;
int R;
L = leftChild(pos);
R = rightChild(pos);
while (pos < Size
&& (Heap[L].minDistance < Heap[pos].minDistance || Heap[R].minDistance < Heap[pos].minDistance)) {
Vertex tmp;
if (Heap[L].minDistance < Heap[R].minDistance) {
elementsPostion[Heap[L].index] = pos;
elementsPostion[Heap[pos].index] = L;
tmp = Heap[L];
Heap[L] = Heap[pos];
Heap[pos] = tmp;
pos = L;
} else {
elementsPostion[Heap[R].index] = pos;
elementsPostion[Heap[pos].index] = R;
tmp = Heap[R];
Heap[R] = Heap[pos];
Heap[pos] = tmp;
pos = R;
}
L = leftChild(pos);
R = rightChild(pos);
/*
* if(pos< Size && Heap[L].minDistance <Heap[pos].minDistance)
* min=L.index; else min=pos; if(R.index<=Size &&Heap[R]<Heap[pos])
* min=R.index; if(min !=pos) { int tmp = Heap[pos]; Heap[pos] =
* Heap[min]; Heap[min] = tmp; minHeapify(min); }
*/
}
// swap in P.Q with Swapping in arrayofVertNum
}
// insert vertex
public void insertVertex(Vertex element) {
Heap[Size] = element; // size = number of verticies
HeapDecreaseKey(Size, element); //
Size++;
}
// Compare when insert with Parents
public void HeapDecreaseKey(int index, Vertex key) // bta5od el element ele hy3mlo insert ,,
{
// index=size , key=element // add in last
// Heap[index]=key; //add in last
Vertex v = new Vertex(key.index, key.xPos, key.yPos, key.minDistance);
//int swap;
boolean b = false;
while (index > 0
&& Heap[parent(index)].minDistance > Heap[index].minDistance) {
b = true;
elementsPostion[Heap[parent(index)].index] = index;
elementsPostion[Heap[index].index] = parent(index);
Vertex tmp = Heap[parent(index)];
Heap[parent(index)] = Heap[index];
Heap[index] = tmp;
index = parent(index);
}
if (b == false)
elementsPostion[key.index] = index;
// Swap in array
}
// check if PQ is empty
public boolean isEmpty() {
return Heap == null;
}
public void display() {
for (int i = 0; i < Size; i++) {
System.out.print(Heap[i].minDistance);
}
System.out.println();
}
}

Keep track of the vertex in the heap using simple index array Positions[Vertex] and record (Vertex,Distance) as element in heap array. But implementing only this is not enough because you need to update positions of vertex very time you do swap operation on heap in any routine.

Related

Why are my generic array elements null? (trying to copy elements into new array)

I have a symbol table class which uses two generic and comparable arrays, Keys[] and Value[]. In main(), I read from input(a text file), and fill the symbol table arrays accordingly. I am trying to create a method, wherein I want to copy Value[] vals into a new array. However, my vals[] elements which make up the symbol table together with Keys[] keys, print null. Why am I getting null, and more importantly, what is a general way to fix this issue?
Since the symbol table has been instantiated, and the arrays have been subsequently filled by put(), I expected vals[z] to contain some integer values which could be used to copy into another array, yet the whole array is null? Some code below is omitted, shown are the main functions put(), get() and rank()
public class SymbolTable<Key extends Comparable<Key>, Value extends Comparable<Value>> {
private Key[] keys;
private Value[] vals;
private int N = 0;
// problem here when trying to copy generic arrays
public void function(int x, int y){
// Copy vals into valscopy
Value[] valscopy;
valscopy = (Value[]) new Comparable[vals.length];
for(int z = 0; z < valscopy.length; z++){
valscopy[z] = vals[z];
}
for(int i = valscopy.length-1; i >= valscopy.length-((y-x)+1); i--){
StdOut.println(valscopy[i] + " " + vals[i]); <------ both print null
}
}
public SymbolTable(int capacity)
{
keys = (Key[]) new Comparable[capacity];
vals = (Value[]) new Comparable[capacity];
}
public Value get(Key key) {
if (isEmpty()) {
return null;
}
int i = rank(key);
if (i < N && keys[i].compareTo(key) == 0) {
return vals[i];
} else {
return null;
}
}
public void put(Key key, Value val) {
int i = rank(key);
// if the same key is found, update value
if (i < N && keys[i].compareTo(key) == 0) {
vals[i] = val;
return;
}
// make room for new key,value pair to be inserted at position i
for (int j = N; j > i; j--) {
keys[j] = keys[j - 1];
vals[j] = vals[j - 1];
}
// insert key and value
keys[i] = key;
vals[i] = val;
N++;
}
public int rank(Key key) {
int lo = 0, hi = N - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
int cmp = key.compareTo(keys[mid]);
if (cmp < 0) {
hi = mid - 1;
} else if (cmp > 0) {
lo = mid + 1;
} else return mid;
}
return lo;
}
boolean contains(Key key) {
return get(key) != null;
}
public int size() {
return N;
}
boolean isEmpty() {
return size() == 0;
}
public static void main(String[] args) {
SymbolTable<String, Integer> st = new SymbolTable<String, Integer>(2000);
String word = "";
while (!StdIn.isEmpty()) {
word = StdIn.readString(); // Read words/keys
if (!st.contains(word)) st.put(word, 1);
else st.put(word, st.get(word) + 1);
}
st.function(3, 7);
}
}

Null pointer exception while implementing Heapify for removing minimum value in MinHeap

For the below program:
public class MinHeap<T extends Comparable<? super T>>
implements HeapInterface<T> {
private T[] backingArray;
private int size;
// Do not add any more instance variables
/**
* Creates a Heap.
*/
public MinHeap() {
backingArray = (T[]) new Comparable[STARTING_SIZE];
size = 0;
}
#Override
public void add(T item) {
if (item == null) {
throw new IllegalArgumentException("Item was null.");
}
if (size + 1 >= backingArray.length) {
resize();
}
backingArray[size + 1] = item;
int i = size + 1;
while (i > 1 && backingArray[i].compareTo(backingArray[i / 2]) <= 0) {
swap(backingArray[i], backingArray[i / 2], i, i / 2);
i = i / 2;
}
size++;
}
private void resize() {
T[] backingArrayTemp = backingArray;
backingArray = (T[]) new Comparable[backingArrayTemp.length * 2];
for (int i = 1; i < size + 1; i++) {
backingArray[i] = backingArrayTemp[i];
}
}
private void swap(T item1, T item2, int i, int parent) {
backingArray[parent] = item1;
backingArray[i] = item2;
}
#Override
public T remove() {
if (isEmpty()) {
throw new NoSuchElementException("Heap is empty.");
}
T temp = backingArray[1];
backingArray[1] = backingArray[size + 1];
size--;
heapify(1);
return temp;
}
private void heapify(int i) {
int left = 2*i;
int right = 2*i + 1;
int min = i;
if (left < size && backingArray[left].compareTo(backingArray[min])
< 0) {
min = left;
}
if (right < size
&& backingArray[right].compareTo(backingArray[min]) < 0) {
min = right;
}
if (min != i) {
swap(backingArray[i], backingArray[min], i, min);
heapify(min);
}
}
#Override
public boolean isEmpty() {
return size == 0;
}
#Override
public int size() {
return size;
}
#Override
public void clear() {
size = 0;
backingArray = (T[]) new Comparable[STARTING_SIZE];
}
We start indexing at i = 1.
My add method works fine, and I've tried changing from backingArray[1] = backingArray[size + 1]; to backingArray[1] = backingArray[size]
in the remove method, but that doesn't seem right and also didn't work. It got rid of the null pointer but didn't pass all my tests. I'm getting null pointers at
backingArray[left].compareTo(backingArray[min]) < 0)
because backingArray[min] is null.
Stack trace
java.lang.NullPointerException
at java.lang.Integer.compareTo(Integer.java:1216)
at java.lang.Integer.compareTo(Integer.java:52)
at MinHeap.heapify(MinHeap.java:68)
at MinHeap.remove(MinHeap.java:60)
I can't really test this, right now, but I think the main problem is in the resize() method. When you create the temporary array to hold the data
T[] backingArrayTemp = backingArray;
you actually tell the new array to point to the same address in the memory as the original backingArray. Then you reallocate backingArray and also the temp array, since they point to the same place in memory. Then, of course, all the elements will not be initialized and the bеhaviour will not be as expected.
The correct way to do this is to create a "new" array and then copy the values:
T[] backingArrayTemp = new T[backingArray.length];
for(int i = 0; i < backingArray.length; ++i)
backingArrayTemp[i] = new T(backingArray[i]);
Where each element is copied with a constructor to avoid similar issues.
About heapify() - I don't know how exactly you will use that min heap, but I guess you will always put the elements one at a time. If you ever need to create the heap from a random array you will need a more complex routine that goes through the entire heap. I can provide you with some more information, if interested.
The problem was I didn't set backingArray[size] = null.

how to delete all the same occurences from an array

So far I have tried to create the method below, but when I run it, the new array leaves zeros for the empty spaces. If a find all method is created to work with this how can it be implemented with a binary search instead of a linear search
package bp;
import java.util.Arrays;
public class SortedList implements IUnsortedList {
/**
* The max size of the List.
*/
public static final int MAX_SIZE = 10000;
/**
* The max value of each occurence.
*/
public static final int MAX_VALUE = 10;
/**
* Flag for the amount of items on the list.
*/
private int sizeOfList = 0;
/**
* Variable to define true or false for duplicates.
*/
private boolean duplicatesAllowed = true;
/**
* Array saves the occurences in the list.
*/
private final int[] listItems = new int[MAX_SIZE];
/**
* Variable for the value to find or delete.
*/
private int searchKey;
/**
* Variable for counter in a loop.
*/
private int f;
#Override
public int getSizeOfList() {
return sizeOfList;
}
#Override
public boolean areDuplicatesAllowed() {
return duplicatesAllowed;
}
#Override
public void setDupliatesAllowed(boolean pDuplicatesAllowed) {
duplicatesAllowed = pDuplicatesAllowed;
}
#Override
public void clear() {
sizeOfList = 0;
}
#Override
public void insert(int pValueToInsert) {
//Loop finds the position of the Item
for (f = 0; f < sizeOfList; f++)
if (listItems[f] > pValueToInsert)
break;
//Loop moves the items after the position up
for (int n = sizeOfList; n > f; n-- )
listItems[n] = listItems[n - 1];
//Insert the Value in the right position
listItems[f] = pValueToInsert;
//Increment List size
sizeOfList++;
}
#Override
public void delete(int pValueToDelete) {
int destroyHAHAHA = find(pValueToDelete);
//If it doesnt find it the item
if (destroyHAHAHA==sizeOfList)
System.out.println("I let you down boss, Can't find "
+ pValueToDelete);
//If it does, kill it with fire
else {
for (int n = destroyHAHAHA; n <sizeOfList; n++)
listItems[n] = listItems[n + 1];
sizeOfList--;
}
}
#Override
public void deleteAll(int pValueToDelete) {
int j = 0;
for(int i = 0; i < listItems.length; i++ )
{
if (listItems[i] != pValueToDelete)
listItems[j++] = listItems[i];
}
int [] newArray = new int[j];
System.arraycopy(listItems, 0, newArray, 0, j );
}
#Override
public void initializeWithRandomData(int pSizeOfList) {
// Loop creates an array with certain number of elements
if (duplicatesAllowed) {
for (int n = 0; n < pSizeOfList; ++n) {
insert(listItems[n] = (int) (Math.random() * MAX_VALUE + 1));
}
} else {
int newvalue=0;
for (int n = 0; n < pSizeOfList; ++n) {
listItems[n] = newvalue++;
++sizeOfList;
}
}
}
#Override
public int find(int pValueToFind) {
searchKey = pValueToFind;
int lowNumber = 0;
int highNumber = sizeOfList - 1;
int result;
while (true) {
result = (lowNumber + highNumber) / 2;
if (listItems[result] == searchKey)
return result;
else if (lowNumber > highNumber)
return sizeOfList;
else {
if (listItems[result] < searchKey)
lowNumber = result + 1;
else
highNumber = result - 1;
}
}
}
#Override
public int[] findAll(int pValueToFind) {
//Array with the location of item
int[] answerArray = new int[sizeOfList];
int searchIndex;
int answerIndex = 0;
for (searchIndex = 0; searchIndex < sizeOfList; searchIndex++) {
if (listItems[searchIndex] == pValueToFind) {
answerArray[answerIndex++] = searchIndex;
}
}
if (answerIndex > 0) {
return Arrays.copyOfRange(answerArray, 0, answerIndex);
} else {
return new int[0];
}
}
#Override
public String toString() {
return Arrays.toString(Arrays.copyOfRange(listItems, 0, sizeOfList));
}
public void bubbleshort(){
int out;
int in;
int middle;
for (out = 0; out < sizeOfList - 1; out++) {
middle = out;
for(in = out +1; in < sizeOfList; in++)
if(listItems[in] < listItems[middle])
middle = in;
selectionSort(out, middle);
}
}
public void selectionSort(int one, int two) {
int temporal = listItems[one];
listItems[one] = listItems[two];
listItems[two] = temporal;
}
}
You can use Common langs ArrayUtils.removeElement() or ArrayUtils.removeAll() method to remove all the elements from the array.
Set contains no duplicates. You can use a Set.
Set<T> mySet = new HashSet<T>(Arrays.asList(someArray));
or
Set<T> mySet = new HashSet<T>();
Collections.addAll(mySet, myArray);

Keeping track of min and max heaps in a Priority Queue

I'm trying to implement a priority queue that allows for deletion of the min and the max values. I'm doing this by creating two heaps within the PQ object and two additional arrays to keep track of the location of the same values in each heap. I'm confused about how to maintain those two arrays when performing a sink, swim, or exchange.
Online, I found the comparison of the two arrays to be a[N] = b[ab[N]] and b[N] = a[ba[N]], but the problem is I don't understand those equations. If someone can offer me some insight, I think I would then be able to maintain the arrays.
Here's my code so far:
public class MyMinMaxPQ<Key extends Comparable<Key>> {
private int N = 0; // number of items on priority queue
private Key[] a; // minheap
private Key[] b; // maxheap
private int[] ab; // index a to b: a[i] == b[ab[i]]
private int[] ba; // index b to a: b[i] == a[ba[i]]
public MyMinMaxPQ(int maxN) { //constructor
a = (Key[]) new Comparable[maxN+1];
b = (Key[]) new Comparable[maxN+1];
ab = new int[maxN+1];
ba = new int[maxN+1];
}
public Key delMin() {
Key min = b[1];
exch(b, 1, N--);
a[N+1] = null;
sink(a, 1);
return min;
}
public Key delMax() {
Key max = a[1]; // Retrieve max key from top.
exch(a, 1, N--); // Exchange with last item.
a[N+1] = null; // Avoid loitering.
sink(a, 1); // Restore heap property.
return max;
}
public void insert(Key item) {
a[++N] = item;
b[++N] = item;
swim(a, N);
swim(b, N);
a[N] = b[ab[N]];
b[N] = a[ba[N]];
}
private void swim(Key[] heap, int k) {
while (k > 1 && less(heap, k/2, k)) {
exch(heap, k/2, k);
k = k/2;
}
}
/**
* Moves the numbers down the heap
* #param heap the heap that the sink will occur on
* #param k the index number on the heap
*/
private void sink(Key[] heap, int k) {
while (2*k <= N) {
int j = 2*k;
if (j < N && less(heap, j, j+1)) j++;
if (!less(heap, k, j)) break;
exch(heap, k, j);
k = j;
}
}
/**
* #param i = first integer to be compared
* #param j = second integer to be compared
* #return <0 : i precedes j; =0 : i and j are equal; >0 : j precedes i
*/
private boolean less(Key[] heap, int i, int j) {
if (heap == a) {
return a[i].compareTo(a[j]) <= 0;
} else {
return b[i].compareTo(b[j]) >= 0;
}
}
/** exchange the two values at indexes i and j in the same heap */
private void exch(Key[] heap, int i, int j) {
Key t = heap[i];
heap[i] = heap[j];
heap[j] = t;
}
/** Is the priority queue empty? */
public boolean isEmpty() {
return N == 0;
}
/** Return the number of items on the priority queue. */
public int size() {
return N;
}
}

Implementing Dijkstra's algorithm using min-heap but failed

I am trying to implement Dijkstra's Algorithm using min-heap in java but getting wrong output every time. Here i fount the same topic in C++. Below is my graph. Node A, which is green colored, is source and Node F, which is red colored, is destination. My objective is to find out the shortest path length from A to F.
Below is my code
public class Dijkstra {
private static Heap heap = new Heap();
private static int[][] graph;
public Dijkstra() {
graph = new int[6][6];
/*
* The graph value assignment is just for checking the code. node A is
* referred as node 0, node B is referred as node 1 and so on. finally
* node F is referred as node 5.
*/
graph[0][0] = graph[0][1] = graph[0][3] = graph[0][4] = graph[0][5] = graph[1][0] = graph[1][1] = graph[1][4] = graph[1][5] = graph[2][2] = graph[2][5] = graph[3][0] = graph[3][3] = graph[4][0] = graph[4][1] = graph[4][4] = graph[5][0] = graph[5][1] = graph[5][2] = graph[5][5] = 0;
graph[1][2] = graph[2][1] = graph[2][3] = graph[3][2] = graph[3][4] = graph[4][3] = graph[4][5] = graph[5][4] = 1;
graph[1][3] = graph[3][1] = 3;
graph[0][2] = graph[2][0] = 4;
graph[2][4] = graph[4][2] = 5;
graph[3][5] = graph[5][3] = 8;
}
public static void main(String[] args) {
Dijkstra dij = new Dijkstra();
// Source is node A (node 0) and destination is node F (node 5)
System.out.println(dij.solve(6, 0, 5));
}
public int solve(int numOfNodes, int source, int dest) {
heap.push(source, 0);
while (!heap.isEmpty()) {
int u = heap.pop();
if (u == dest)
return heap.cost[dest];
for (int i = 0; i < numOfNodes; i++) {
if (graph[u][i] >= 0)
heap.push(i, heap.cost[u] + graph[u][i]);
}
}
return -1;
}
}
class Heap {
private int[] data;
private int[] index;
public int[] cost;
private int size;
public Heap() {
data = new int[6];
index = new int[6];
cost = new int[6];
for (int i = 0; i < 6; i++) {
index[i] = -1;
cost[i] = -1;
}
size = 0;
}
public boolean isEmpty() {
return (size == 0);
}
private void shiftUp(int i) {
int j;
while (i > 0) {
j = (i - 1) / 2;
if (cost[data[i]] < cost[data[j]]) {
// swap here
int temp = index[data[i]];
index[data[i]] = index[data[j]];
index[data[j]] = temp;
// swap here
temp = data[i];
data[i] = data[j];
data[j] = temp;
i = j;
} else
break;
}
}
private void shiftDown(int i) {
int j, k;
while (2 * i + 1 < size) {
j = 2 * i + 1;
k = j + 1;
if (k < size && cost[data[k]] < cost[data[j]]
&& cost[data[k]] < cost[data[i]]) {
// swap here
int temp = index[data[k]];
index[data[k]] = index[data[i]];
index[data[i]] = temp;
// swap here
temp = data[k];
data[k] = data[i];
data[i] = temp;
i = k;
} else if (cost[data[j]] < cost[data[i]]) {
// swap here
int temp = index[data[j]];
index[data[j]] = index[data[i]];
index[data[i]] = temp;
// swap here
temp = data[j];
data[j] = data[i];
data[i] = temp;
i = j;
} else
break;
}
}
public int pop() {
int res = data[0];
data[0] = data[size - 1];
index[data[0]] = 0;
size--;
shiftDown(0);
return res;
}
public void push(int x, int c) {
if (index[x] == -1) {
cost[x] = c;
data[size] = x;
index[x] = size;
size++;
shiftUp(index[x]);
} else {
if (c < cost[x]) {
cost[x] = c;
shiftUp(index[x]);
shiftDown(index[x]);
}
}
}
}
While running this whole code, i am getting 0 as output but one can clearly tell the cost from node A to node F is 7 (4+1+1+1 = A-C-D-E-F). Where is the error?
You test for an existing edge using graph[u][i] >= 0. But your graph is defined to have no edge for value zero. So you should change it to
if (graph[u][i] > 0) ...
inside method solve. Another possibility is to mark non-existing edges with a value of -1 in your matrix. This would then also allow for zero-cost edges.
In the heap, you have two values:
index that identifies the node,
and cost that identify the distance of the node.
You pop the cost, that is the distance, but you used it like the index to identify the node.
public int pop() {
int res = data[0];
...
return res;
}
and in solve():
int u = heap.pop();
if (u == dest)
...

Categories