1

The following code simulates finding the closest pair but when I generate a random amount of pairs greater than 250 it throws a stack overflow error. But 250 pairs and any even amount under seem to work fine. Any ideas?

The error occurs at the recursive call of ComparePoints under the if statement.

public class Divide {

    Point2D closest1;
    Point2D closest2;
    double Distance = Double.MAX_VALUE;

    public Divide(Point2D[] RandArray){
        SortArray s = new SortArray();
        RandArray = s.SortPointsX(RandArray);
        SplitAndConquer(RandArray);
    }

    private double ComparePoints(Point2D a, Point2D b, Point2D[] s, 
                int CurrentPoint, int NextPoint){
            if(s[CurrentPoint] != null && s[NextPoint] != null){
                if (Distance > a.distance(b) && 
                        (a.getX() != b.getX() || a.getY() != b.getY())){
                    Distance = a.distance(b);
                    closest1 = new Point2D.Double(a.getX(), a.getY());
                    closest2 = new Point2D.Double(b.getX(), b.getY());
                }
                if (NextPoint == (s.length - 1)){
                    NextPoint = s.length - ((s.length - 1) - CurrentPoint);
                    CurrentPoint++;
                }
                if (CurrentPoint != (s.length - 1)){
                    if (NextPoint != (s.length - 1)){
                    NextPoint++;
                    ComparePoints(s[CurrentPoint], s[NextPoint],
                            s, CurrentPoint, NextPoint);
                    }
                }
                if (CurrentPoint == (s.length - 1)){
                    CurrentPoint = 0;
                    NextPoint = 0;
                }
            }
         return Distance;
    }

    private void SplitAndConquer(Point2D[] RandArray){
        double median = RandArray[RandArray.length/2].getX();
        int countS1 = 0;
        int countS2 = 0;
        boolean exact = false;
        int CurrentPoint = 0;
        int NextPoint = 0;
        Point2D[] s1 = new Point2D[RandArray.length/2];
        Point2D[] s2 = new Point2D[RandArray.length/2];

        for (int i = 0; i < RandArray.length; i++){

            if (RandArray[i].getX() < median){
                s1[countS1] = RandArray[i];
                countS1++;
            }
            else if (RandArray[i].getX() > median){
                s2[countS2] = RandArray[i];
                countS2++;
            }
            else if (RandArray[i].getX() == median && exact == false){
                s2[countS2] = RandArray[i];
                exact = true;
                countS2++;
            }
            else if (RandArray[i].getX() == median && exact == true) {
                s1[countS1] = RandArray[i];
                exact = false;
                countS2++;
            }
        }

        if (s1[0] != null && s1[1] != null){
            Distance = ComparePoints(s1[0], s1[1], s1,
                    CurrentPoint, NextPoint);
            Distance = ComparePoints(s2[0], s2[0], s2,
                    CurrentPoint, NextPoint);
            }else{
                System.out.println
                ("One of the subsets does not contain enough points!");
            }
        CheckMid(RandArray, Distance, median, CurrentPoint, NextPoint);
        PrintClosest();
        }

    private void PrintClosest() {
        System.out.println("The closest pair found using Divide "
                + "And Conquer is at ("
                + closest1.getX() + " " + closest1.getY() + "), and (" 
                + closest2.getX() + " " + closest2.getY() + ")");
        System.out.println("The distance between the pairs is: " + Distance);

    }

    private void CheckMid(Point2D[] randArray, double d, double m,
            int current, int next) {
        int MidCount = 0;
        Point2D[] MidArray = new Point2D[randArray.length];
        for(int i = 0; i < randArray.length; i++){
            if(randArray[i].getX() > (m - d) && 
                    randArray[i].getX() < (m + d)){
                MidArray[MidCount] = randArray[i];
                MidCount++;
            }
        }
        if (MidArray[0] != null && MidArray[1] != null){
        ComparePoints(MidArray[0], MidArray[1], MidArray,
                current, next);
        }
    }
}
azurefrog
  • 10,785
  • 7
  • 42
  • 56
  • "but when I generate a random amount of pairs greater than 250 it throws a stack overflow error" - any stack is a finite size. either increase size or alter algorithm. – Mitch Wheat Mar 29 '16 at 03:15
  • I would like to try and alter the algorithm but I'm not sure how to go about it, any advice? – Matt Wallace Mar 29 '16 at 17:46

2 Answers2

1

Sounds like you're exceeding the the amount of stack memory allocated for your program. You can change the stack size with the -Xss option. E.g java -Xss 8M to change stack size to 8MB and run your program.

zMesh
  • 78
  • 5
  • Is there a way to change the program to accommodate larger amount of recursive calls without changing the stack size? – Matt Wallace Mar 29 '16 at 17:47
0

Internally Java has call stack, that stores the method calls as stack frames. And it process these method calls (frames) in LIFO manner. when a new thread is created (in your case a main thread) a fixed amount of stack and heap memory is allocated to that thread. So whenever the call stack gets exhausted we get a stackoverflow error. In your case the number of recursive calls has exceeded the size of call stack, and so you are getting the Error.

Ajinkya Kale
  • 127
  • 1
  • 12