High memory usage in java program (lots of recursion with arrays) - java

I am having a problem that has been bugging me for few days now. I am doing a college asignment where i have to multiply 2 big numbers (each number can be up to 10000 digits), for that reason i have to use arrays.
I have to use naive divide and conquer method using a special formula and it is working, i get the correct output.
The problem though is that program's ram usage peaks at 715MB while the college server which will test my outputs only permits peaks less then 10MB !
I used visualVM to get some statistics and it shows that at the end of main method i have over 25.000 int arrays opened, which obviously means that garbage collector won't clean them. I tried manualy removing arrays by array = null but it has no effect. Even more, size of arrays in program has no effect on ram usage, if i make all arrays of size 10000 or if i make them smaller, ram usage is still 715MB. Nothing i tried has made even 1Kb difference in ram usage. What am i doing wrong ?
import java.util.*;
public class Naloga2 {
static int firstNumberLength;
static int secondNumberLength;
static int count;
public static void main(String[] args) {
firstNumberLength = 0;
secondNumberLength = 0;
start(args);
System.out.println("Check memory usage and press any key");
Scanner scan = new Scanner(System.in);
scan.nextLine();
}
static void printArray(int[] a, int length) {
for(int i=0;i<length;i++) System.out.print(a[i]);
System.out.println();
}
static void printArrayNoNewLine(int[] a, int length) {
for(int i=0;i<length;i++) System.out.print(a[i]);
}
static int[] obrniTabelo(int[] tabela, int dolzinaTabele) {
int[] novaTabela = new int[firstNumberLength + secondNumberLength];
for(int i=0;i<dolzinaTabele;i++) {
novaTabela[i] = tabela[dolzinaTabele - i - 1];
}
return novaTabela;
}
static void readNumbers(int[] a, int[] b) {
Scanner sc = new Scanner(System.in);
String temp1 = "1814760427359093701773634896055154238604621068079345503988844965147764988324706056377247443923778795928948605699104801900306908537904148935233121873094936503998915865745862371767010306054062906768898568957847355344002122176514654744790212626620584107994283130875249861052935175219132106429755509971192581933953801388381188460986660581979158129483917001271702223407654800335931472019985629221607213865018069283189966200621625300134";
String temp2 = "97512060979417027247066473890437645860252983792423404628415959133594150264916901106891610016700858329869623573382829998749019896997745761637960733420798357562414782788848733769941600640359229331196534760613331886605807310229536529299047661042932723686940506490467693828359124032044766542882911974806517818312853119004786073768385133003204124346870416398337405003873260912959735781385513491033737150032844086069531948792576932151901897811096445945530418292434773408981209319417729967465446257427784080363848953538788259430643983374127862528899812266699138053211381274176090725067261872355977420957399650610409274997690573284775365452519492094199150332836530293736450846555043855394905294740708235099468050036111579819724363868989787277506605869758256547608040247461962450653542826639244219294087064008107664753142535552152880164752050308970662812876788273331513642358933315796998961151437131149920030780118660547331872894504653590764949555989125948482198399816531852334011945495558518939896596518131272300822293060394523495515862731265541258202053045616084735425799134171661329905235453695720851880506732702524221829703587444566936446048580047972702945614278702240636251666791566010549308512827456794434888225729025123511920552233844557238739513734443927750297099927757353661453279831551902974620243283691649185034824294607701567938075725970651517685420371143465190361476038554928265834067374093805712372282561321345651430079136538347289657425955000036298701183558407903511884604388721633166414508318158";
firstNumberLength = temp1.length();
secondNumberLength = temp2.length();
for(int i=0;i<firstNumberLength;i++) a[i] = temp1.charAt(i) - 48;
for(int i=0;i<secondNumberLength;i++) b[i] = temp2.charAt(i) - 48;
}
static void start(String[] args) {
int a[] = new int[10000];
int b[] = new int[10000];
readNumbers(a, b);
int aa[] = new int[firstNumberLength];
int bb[] = new int[secondNumberLength];
for(int i=0;i<firstNumberLength;i++) aa[i] = a[i];
for(int i=0;i<secondNumberLength;i++) bb[i] = b[i];
dv(aa, bb, "count");
}
static int[] steviloPlusSteviloRu (int[] a, int[] b, int[] tempDolzina) {
a = obrniTabelo(a, tempDolzina[0]);
b = obrniTabelo(b, tempDolzina[1]);
int prenos = 0;
if(tempDolzina[0] < tempDolzina[1]) {
tempDolzina[0] = tempDolzina[1];
}
int limit = tempDolzina[1];
for(int i=0;i<tempDolzina[1];i++) {
a[i] = a[i] + b[i] + prenos;
prenos = 0;
if(a[i] > 9) {
prenos = a[i] / 10;
a[i] = a[i] % 10;
}
}
while(prenos > 0) {
if(prenos > 9) System.out.println("prenos nad 9, error !");
a[limit] = a[limit] + prenos;
prenos = 0;
if(a[limit] > 9) {
prenos = a[limit] / 10;
a[limit] = a[limit] % 10;
}
if(limit == tempDolzina[0]) tempDolzina[0]++;
limit++;
}
a = obrniTabelo(a, tempDolzina[0]);
return a;
}
static int[] stevkaKratSteviloDv(int[] a, int b, int[] length) { // dv - mnozenje z stevko
int prenos = 0;
a = obrniTabelo(a, length[0]);
for(int i=0;i<length[0];i++) {
a[i] = a[i] * b + prenos;
prenos = 0;
if(a[i] > 9) {
prenos = a[i] / 10;
a[i] = a[i] % 10;
}
}
if(prenos > 0 ) {
if(prenos > 9) System.out.println("prenos vecji od 9 !!");
a[length[0]] = prenos;
length[0]++;
}
a = obrniTabelo(a, length[0]);
return a;
}
static void dv(int[] a, int[] b, String m) { // dk
int mode = 0;
if(m.equals("count")) mode = 1;
if(mode == 1) {
printArray(a, firstNumberLength);
printArray(b, secondNumberLength);
}
int[] dolzine = {firstNumberLength, secondNumberLength};
int[] dolzina = {firstNumberLength, secondNumberLength};
int[] len1 = {firstNumberLength};
int[] len2 = {secondNumberLength};
int[] len3 = new int[1];
int[] rezultat = dvRek(a, b, len1, len2, len3, mode);
rezultat = odstrani(rezultat, len3);
if(mode == 0) {
printArray(rezultat, len3[0]);
} else System.out.println(count);
}
static int[] subSet(int[] aa, int[] length, int mode) { // returns subset, depends on mode
int dolzina = length[0];
if(dolzina < 2) {
System.out.println("error, dolzina je " + dolzina);
return aa;
}
int start = 0;
int stop = dolzina / 2;
if(mode == 1) {
start = dolzina / 2;
stop = dolzina;
}
int[] temp = new int[length[0]];
int index = 0;
for(int i=start;i<stop;i++) {
temp[index] = aa[i];
index++;
}
length[0] = (stop - start);
aa = null;
return temp;
}
static int[] dodajNicle(int[] aa, int[] length, int num) { // adds zeroes, basicly multiplying with 10^num
int[] temp = new int[length[0] + num];
for(int i=0;i<length[0];i++) temp[i] = aa[i];
for(int i=0;i<num;i++) {
temp[length[0]] = 0;
length[0]++;
}
aa = null;
return temp;
}
static int[] dopolni(int[] aa, int[] length, int num) { // adds num zeros at start and returns
aa = obrniTabelo(aa, length[0]);
int start = length[0];
int end = start + num;
for(int i=start;i<end;i++) aa[i] = 0;
length[0] = length[0] + num;
aa = obrniTabelo(aa, length[0]);
return aa;
}
static int[] odstrani(int[] aa, int[] length) { // removes zeros from beginning
aa = obrniTabelo(aa, length[0]);
for(int i=(length[0]-1);i>0;i--)
if(aa[i] == 0) length[0]--;
else break;
aa = obrniTabelo(aa, length[0]);
return aa;
}
static int[] dvRek (int[] a, int[] b, int[] lengthA, int[] lengthB, int[] lengthC, int mode) {
a = odstrani(a, lengthA);
b = odstrani(b, lengthB);
if(mode == 0) {
printArrayNoNewLine(a, lengthA[0]);
System.out.print(" ");
printArray(b, lengthB[0]);
}
if(lengthA[0] == 1) {
if(a[0] == 0) {
lengthC[0] = 1;
return new int[1];
}
int temp = lengthB[0];
int minus = 0;
for(int i=0;i<temp;i++) {
if(b[i] == 0) minus++;
if(b[i] > 0) break;
}
count = count + temp - minus;
b = stevkaKratSteviloDv(b, a[0], lengthB);
lengthC[0] = lengthB[0];
lengthB[0] = temp;
return b;
} else if (lengthB[0] == 1) {
if(b[0] == 0) {
lengthC[0] = 1;
return new int[1];
}
int temp = lengthA[0];
int minus = 0;
for(int i=0;i<temp;i++) {
if(a[i] == 0) minus++;
if(a[i] > 0) break;
}
count = count + temp - minus;
a = stevkaKratSteviloDv(a, b[0], lengthA);
lengthC[0] = lengthA[0];
return a;
} else {
if(lengthA[0] > lengthB[0]) {
b = dopolni(b, lengthB, (lengthA[0] - lengthB[0]));
}
else if (lengthA[0] < lengthB[0]) {
a = dopolni(a, lengthA, (lengthB[0] - lengthA[0]));
}
int[] a1Len = { lengthA[0] };
int[] a0Len = { lengthA[0] };
int[] b1Len = { lengthB[0] };
int[] b0Len = { lengthB[0] };
int[] a1 = subSet(a, a1Len, 0);
int[] a0 = subSet(a, a0Len, 1);
int[] b1 = subSet(b, b1Len, 0);
int[] b0 = subSet(b, b0Len, 1);
a = null;
b = null;
int[] temp = new int[1];
int[] tempp = new int[1];
temp[0] = b0Len[0];
tempp[0] = a0Len[0];
int[] a0b0 = dvRek(a0, b0, tempp, temp, lengthC, mode);
int[] a0b0Len = { lengthC[0] };
temp[0] = b1Len[0];
tempp[0] = a0Len[0];
int[] a0b1 = dvRek(a0, b1, tempp, temp, lengthC, mode);
int[] a0b1Len = { lengthC[0] };
//a1b0
temp[0] = b0Len[0];
tempp[0] = a1Len[0];
int[] a1b0 = dvRek(a1, b0, tempp, temp, lengthC, mode);
int[] a1b0Len = { lengthC[0] };
//a1b1
temp[0] = b1Len[0];
tempp[0] = a1Len[0];
int[] a1b1 = dvRek(a1, b1, tempp, temp, lengthC, mode);
int[] a1b1Len = { lengthC[0] };
int n = lengthA[0];
if(lengthB[0] > n) n = lengthB[0];
if(n % 2 != 0) n++;
int[] temp1 = dodajNicle(a1b1, a1b1Len, n );
int[] dolzine = {a0b1Len[0], a1b0Len[0]};
int[] temp2 = steviloPlusSteviloRu(a0b1, a1b0, dolzine);
temp2 = dodajNicle(temp2, dolzine, (n/2) );
int[] dolzine1 = {a1b1Len[0], dolzine[0]};
int[] temp3 = steviloPlusSteviloRu(temp1, temp2, dolzine1);
int[] dolzine2 = {dolzine1[0], a0b0Len[0] };
int[] temp4 = steviloPlusSteviloRu(temp3, a0b0, dolzine2);
lengthC[0] = dolzine2[0];
a = null;
b = null;
a0b0 = null;
a1b0 = null;
a0b1 = null;
a1b1 = null;
a0 = null;
a1 = null;
b0 = null;
b1 = null;
lengthA = null;
lengthB = null;
lengthC = null;
temp = null;
tempp = null;
dolzine = null;
dolzine1 = null;
dolzine2 = null;
temp1 = null;
temp2 = null;
temp3 = null;
return temp4;
}
}
}

Related

Java finding the smallest integer in a speciofic position in a sets of integer

Algorithm:
Procedure SELECT( k,S)
{ if ISI =1 then return the single element in S
else { choose an element a randomly from S;
let S1,S2,and S3 be he sequences of elements in S
less than, equal to, and greater than m, respectively;
if IS1I >=k then return SELECT(k,S1)
else
if (IS1I + IS2I >=k then return m
else return SELECT(k-IS1I-IS2I , S3);
}
}
The question is to implement the first algorithm for finding the kth smallest integer in a set of integers and test your program for different sets of integers generated by a random number generator.
Below is my solution.
import java.util.Random;
import java.util.Scanner;
public class main {
private static Random rand = new Random();
private static Scanner keyboard = new Scanner(System.in);
public static int firstAlgorithm(int k, int[] S) {
int m = S[rand.nextInt(S.length)];
int[] S1 = new int[S.length];
int[] S2 = new int[S.length];
int[] S3 = new int[S.length];
int p = 0;
int q = 0;
int r = 0;
if (S.length == 1)
return S[0];
for (int i = 0; i < S.length; i++) {
if (S[i] < m) {
S1[p] = S[i];
p++;
} else if (S[i] == m) {
S2[q] = S[i];
q++;
} else {
S3[r] = S[i];
r++;
}
}
S1 = trimToSize(S1, p);
S2 = trimToSize(S2, q);
S3 = trimToSize(S3, r);
if (S1.length >= k)
return firstAlgorithm(k, S1);
else if (S1.length + S2.length >= k)
return m;
else
return firstAlgorithm(k - S1.length - S2.length, S3);
}
private static int[] trimToSize(int[] arr, int size) {
int[] temp = new int[size];
for (int i = 0; i < size; i++) {
temp[i] = arr[i];
}
return temp;
}
public static void printArray(int[] S) {
for (int i = 0; i < S.length; i++) {
System.out.print(S[i] + "\t");
if (i % 10 == 9)
System.out.println();
}
}
// start main method
public static void main(String[] args) {
System.out.print("Enter the size of an array: ");
int size = keyboard.nextInt();
while (size < 1) {
System.out.println("Size of the array should be greater than 0.");
System.out.print("Enter the size of an array: ");
size = keyboard.nextInt();
}
System.out.print("Enter the value of k: ");
int k = keyboard.nextInt();
while (k < 1 || k > size) {
System.out.println("Value of k should be in the range 1-" + size + ".");
System.out.print("Enter the value of k: ");
k = keyboard.nextInt();
}
int[] S = new int[size];
for (int i = 0; i < size; i++) {
S[i] = 100 + rand.nextInt(900);
}
System.out.println("\nRandom values generated in the array:");
printArray(S);
System.out.println();
System.out.println(k + "th smallest value in the array using Algorithm #1: " + firstAlgorithm(k, S));
}
}
But I need to implement the above algorithm without using a temporary array for partitioning. How can I do it?
The algorithm is Dijkstra's 3-way partition.
You will have to modify the original S.
Untested (pseudo) code ahead
public static int partition(int left, int right, int[] S) {
int m = rand.nextInt(right-left); // protect against malicious data
swap(S[left+m], S[right]);
int equal = left;
while (left < right) {
if (a[left] < a[n])
swap(S, left++, equal++)
else if (a[left] == a[n])
swap(S, left, --right);
else
left++;
}
return left, equal;
}
public static int firstAlgorithm(int k, int left, int right, int[] S) {
if (left == right)
return S[left];
int p, e = partition(left, right, S); // returns 2 values. S1=[0,p), S2=[p,e), S3=[e, n)
if (p >= k)
return firstAlgorithm(k, left, p, S);
else if (e >= k) // p < k
return S[p]; // p is the first equal, e is first larger than equal
else // e < k
return firstAlgorithm(k, e, right, S);
}
// test
S = {1, 4, 2, 6, 2};
k = 2;
int result = firstAlgorithm(2, 0, S.length-1, S);
assert(result == 2);
Warning syntax and off-by-one errors guarantied.
See here multiple ways to return 2 values in java.

In my Java merge sort fucntion, even when the condition is false, it is entering the loop. Why?

In my "merge" function, in the while loop, the given condition is a!=null && b!=null, but when b is null, it still enters the while loop and then later gives an error.
int[] merge(int[]a, int[]b)
{
int length = a.length+b.length;
int[]c = new int[length];
while (a!=null && b!=null)
{
if (a[0]<b[0])
{
c[length-1]=a[0];
a = tail(a);
}
else
{
c[length-1]=b[0];
b = tail(b);
}
}
return c;
}
int[] mergeSort(int[]a)
{
if (a.length==1)
return a;
int[] q = new int[a.length];
int[] l = new int[a.length/2];
int [] r = new int[a.length-l.length];
for (int i=0; i<l.length; i++)
{
l[i] = a[i];
}
for (int i=l.length; i<r.length; i++)
{
r[i-l.length] = a[i];
}
q = merge(mergeSort(l), mergeSort(r));
return q;
}
I think, you're facing situation when one of array (either a or b) is already empty, and the other one - still has elements. So, in the merge function you should take this into account.
This is full implementation of your mergeSort:
public class Answer {
public static void main(String[] args) {
int[] unsorted = new int[]{4,3,4,2,1,1,3,3,3,3,3,5,6,6,9,9,10,7,7,8};
System.out.println(Arrays.toString(mergeSort(unsorted)));
}
public static int[] mergeSort(int[]a) {
if (a.length == 1) return a;
int[] q = new int[a.length];
int[] l = new int[a.length / 2];
int [] r = new int[a.length - l.length];
for (int i = 0; i < l.length; i++) {
l[i] = a[i];
}
for (int i = 0; i < r.length; i++) {
r[i] = a[l.length + i];
}
q = merge(mergeSort(l), mergeSort(r));
return q;
}
private static int[] merge(int[]a, int[]b) {
int length = a.length + b.length;
int[] c = new int[length];
int p = 0;
while (a.length > 0 && b.length > 0) {
if (a[0] < b[0]) {
c[p++] = a[0];
a = tail(a);
} else {
c[p++] = b[0];
b = tail(b);
}
}
while (a.length > 0) {
c[p++] = a[0];
a = tail(a);
}
while (b.length > 0) {
c[p++] = b[0];
b = tail(b);
}
return c;
}
private static int[] tail(int[] a) {
int[] t = new int[a.length - 1];
for (int i = 0; i < t.length; i++) {
t[i] = a[i + 1];
}
return t;
}
}
Actually you have a problem with the auxiliary method merge().
I strongly recommend you to take this as an opportunity to practice systematic testing of your methods. Consider that we all constantly make mistakes when we write programs, and spotting errors to correct them is a real part of the job.
What make it easier, is to anticipate over this matter of fact : sh*t happens. And take time to write down some test cases, with input data and expected results.
int[] empty = {};
int [] r1 = merge(empty, empty);
System.out.println("Result should be empty\n");
printArray(r1);
int [] oneElement = { 23 };
int [] r3 = merge(oneElement, empty);
System.out.println("Result should be [23]\n");
printArray(r2);
...
So you have automated tests (we're all too lazy to do it by hand every time after the 35th modification of the codeĀ°.
This will lead you to "unit tests"....

Jumping Frogs (Frog Puzzle) using DFS

I have been trying to implement the Jumping Frogs puzzle (here is a good link to what I mean http://britton.disted.camosun.bc.ca/frog_puzzle.htm) in Java with the goal being to print out the steps from the beginning to the right ending (successfull solution).
I am using an Arraylist to write the nodes I have already visited and a stack to get back to parent nodes if necessary.
However, the program prints odd things, although the algorithm seems to be working fine...any ideas why is this happening and how can I fix this?
public class JumpingFrogs {
public static int indexOfZero(int arr[]){
int index=0;
for (int i=0; i <arr.length; i++){
if (arr[i]==0) index = i;
}
return index;
}
public static int[] swap(int[] arr, int ind1, int ind2){
int temp = arr[ind1];
arr[ind1] = arr[ind2];
arr[ind2] = temp;
return arr;
}
public static int[] makeCopy(int[] arr){
int[] copy = new int[arr.length];
for (int i = 0; i < copy.length; i++){
copy[i] = arr[i];
}
return copy;
}
public static boolean isContained(int[] arr, ArrayList arrayList){
if(arrayList.isEmpty()) return false;
for (Object arrayList1 : arrayList) {
if (Arrays.equals(arr, (int[]) arrayList1)) {
return true;
}
}
return false;
}
public static void main(String[] args) {
System.out.print("Input number of frogs on each side: ");
Scanner input = new Scanner(System.in);
int frogNumber = input.nextInt();
int[] root = new int[2*frogNumber + 1];
int[] solution = new int[2*frogNumber + 1];
for (int i = 0; i < 2*frogNumber + 1; i++){
if (i < frogNumber){
root[i] = 1;
solution[i]=2;
}
else{
if (i == frogNumber){
root[i] = 0;
solution[i] = 0;
}
else{
root[i] = 2;
solution[i] = 1;
}
}
}
Stack stack = new Stack();
ArrayList visitedNodes = new ArrayList();
stack.push(makeCopy(root));
do{
int i0=indexOfZero(root);
if((i0 >= 2)&&(root[i0-2] == 1)&&(!isContained((swap(makeCopy(root), i0 - 2, i0)), visitedNodes))){
swap(root, i0 - 2, i0);
stack.push(makeCopy(root));
visitedNodes.add(makeCopy(root));
continue;
}
if((i0 >= 1)&&(root[i0-1] == 1)&&(!isContained((swap(makeCopy(root), i0 - 1, i0)), visitedNodes))){
swap(root, i0 - 1, i0);
stack.push(makeCopy(root));
visitedNodes.add(makeCopy(root));
continue;
}
if((i0 < root.length - 1)&&(root[i0+1] == 2)&&(!isContained((swap(makeCopy(root), i0+1, i0)), visitedNodes))){
swap(root, i0 + 1, i0);
stack.push(makeCopy(root));
visitedNodes.add(makeCopy(root));
continue;
}
if((i0 < root.length - 2)&&(root[i0+2] == 2)&&(!isContained((swap(makeCopy(root), i0+2, i0)), visitedNodes))){
swap(root, i0 + 2, i0);
stack.push(makeCopy(root));
visitedNodes.add(makeCopy(root));
continue;
}
stack.pop();
root=(int[]) stack.peek();
}
while(!Arrays.equals(root, solution));
Stack path = new Stack();
while(!stack.empty()){
path.push(stack.pop());
}
while(!path.empty()){
int[] step = (int[]) path.pop();
for (int p = 0; p < step.length; p++){
System.out.print(step[p]);
}
System.out.println();
}
System.out.println("The program has ended successfully!");
}
}
try clone root like,
do{
proccessing
.
.
.
.
.
.
stack.pop();
root=(int[]) stack.peek();
//add
root = root.clone();
}

Java Array Index out of Bounds Error

I'm working on a brute force approach to the traveling salesman problem. I have a certain line that produces the ArrayIndexOutOfBounds exception, however all the arrays used there have more than enough space. The particular line of code:
testCity[0][a] = cities[0][(int) cityList[a]];
This is where I initialize testCity:
int[][] testCity = new int[2][CITIES+10];
cities:
public static int[][] cities = new int[2][CITIES+10];
And, finally, cityList:
Object[] cityList = new Integer[CITIES+10];
This is the entire error message:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
at BruteF.permute(BruteF.java:39)
at BruteF.permute(BruteF.java:30)
at BruteF.permute(BruteF.java:30)
at BruteF.permute(BruteF.java:30)
at BruteF.main(BruteF.java:11)
And here is the code:
public class BruteF {
public static final int CITIES = 5;
public static int[][] cities = new int[2][CITIES+10];
public static int[][] bestCity = new int[2][CITIES+10];
public static double bestDistance = 1000;
public static int[][] testCity = new int[2][CITIES+10];
public static Object[] cityList = new Integer[CITIES+10];
public static void main(String[] args)
{
permute(java.util.Arrays.asList(1,2,3,4), 0);
for (int i = 0;i < CITIES;i++)
{
System.out.println(bestCity[0][i] + "," + bestCity[1][i]);
}
}
static void permute(java.util.List<Integer> arr, int k){
cities[0][0] = 1;
cities[1][0] = 1;
cities[0][1] = 2;
cities[1][1] = 5;
cities[0][2] = 3;
cities[1][2] = 2;
cities[0][3] = 4;
cities[1][3] = 3;
int originalX = cities[0][0];
int originalY = cities[1][0];
for(int i = k; i < arr.size(); i++){
java.util.Collections.swap(arr, i, k);
permute(arr, k+1);
java.util.Collections.swap(arr, k, i);
}
if (k == arr.size() -1){
for (int i = 0;i < CITIES;i++)
{
cityList = arr.toArray();
for (int a = 0;a < CITIES;a++)
{
testCity[0][a] = cities[0][(int) cityList[a]];
}
if (distance(testCity,CITIES,originalX, originalY) < bestDistance)
{
bestCity = testCity;
bestDistance = distance(testCity,CITIES, originalX, originalY);
}
}
}
}
static double distance (int[][] cities, int CITIES, int originalX, int originalY)
{
int[][] taken = new int[2][CITIES+1];
int takenCounter = 0;
double distance = 0;
cities[0][CITIES] = cities[0][0];
cities[1][CITIES] = cities[1][0];
for (int i = 0;i <= CITIES;i++)
{
for (int z = 0;z <= CITIES;z++)
{
if (cities[0][i] == taken[0][z] && cities[1][i] == taken[1][z])
{
return CITIES*1000; //possible error here
}
else {
taken[0][takenCounter] = cities[0][i];
taken[1][takenCounter] = cities[1][i];
}
}
if (cities[0][0] != originalX && cities[1][0] != originalY)
{
return CITIES*1000; //POSSIBLE BUG HERE
}
distance = distance + Math.sqrt(Math.pow(cities[0][i+1]-cities[0][i],2) + Math.pow(cities[1][i+1]-cities[1][i],2));
}
return distance;
}
}
Why is this happenening? What can I do to fix it?
It is giving out of bound exception : 4
when you are initializing cityList i.e. cityList = arr.toArray(); your array cityList[] = {1,2,3,4} , i.e of size 4 from 0 to 3.
And you are running a for loop i.e
for (int a = 0;a < CITIES;a++)
from a=0 to CITIES , so as the moment arrive when a=4, it gives out of bound error.

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