Search code examples
javasortingrecursionmergesort

simple recursive merge sort Stack java.lang.StackOverflowError


I have a simple recursive merge sort, I am just try to sort an array list of Integers that implement Comparable. I don't under stand why I am getting an error, when it runs it prints out the ArrayList of random Integers that I created and then it prints

no error yet

no error yet

Exception in thread "main" java.lang.StackOverflowError

and then it repeats

at MergeTemplate.rMerge(MergeTemplate.java:38)

a bunch of times until it finally says

Process complete

import java.util.*;
public class MergeTemplate{
private ArrayList <Comparable> temp1=new <Comparable> ArrayList();
int num;
Random ar=new Random();
public MergeTemplate(){
    num=25;
}
  public MergeTemplate(int n){
    num=n;
  }
      public ArrayList <Comparable> fillArray(){
          ArrayList <Comparable> ar1=new <Comparable> ArrayList();
          for(int i=0;i<num; i++)
              ar1.add(ar.nextInt(11));
          screenOutput(ar1);
      return ar1;
      }
      public void screenOutput(){
          for(Comparable x: temp1)
              System.out.print(x+ " ");
          System.out.println();
      }
      public void screenOutput(ArrayList <Comparable> temp){
          for(Comparable x: temp)
              System.out.print(x+ " ");
          System.out.println();
      }
      public void rMerge(ArrayList <Comparable> rList){
          rMerge(rList, 0, rList.size()-1);
      }

      public void rMerge(ArrayList <Comparable> rList, int first, int last){
          if (first-last==0){
              System.out.println("no error yet");
          }
          else{
              rMerge(rList, first, last/2);
              rMerge(rList, last/2 + 1, last);
              merge(rList, first, last);
          }
      }
      public void merge(ArrayList <Comparable> a, int first, int last){
          Comparable placeHolder;
          if(a.get(first).compareTo(a.get(last))>1){
              placeHolder=a.get(first);
              a.set(first, a.get(last));
              a.set(last, placeHolder);
          }
      }
}

public class Tester {
    public static void main(String[] args) {
    MergeTemplate one=new MergeTemplate(8);
    one.rMerge(one.fillArray());
    }
}

Solution

  • You need one more key to represent the split point to divide the elements appropriately. The merge () method also needs to be re-implemented to iterate over all target elements. The complete code with an implementation of the rMerge() method adding a single key called mid and an implementation of the merge() method as shown below.

    import java.util.ArrayList;
    import java.util.Random;
    
    public class MergeTemplate {
    
        private Random random = new Random();
    
        private ArrayList<Comparable> temp1 = new ArrayList<>();
        private int num;
    
    
        public MergeTemplate() {
            this.num = 25;
        }
    
        public MergeTemplate(int num) {
            this.num = num;
        }
    
        public ArrayList<Comparable> fillArray() {
            ArrayList<Comparable> ar1 = new ArrayList<>();
    
            for (int i = 0; i < num; i++) {
                ar1.add(random.nextInt(11));
            }
            screenOutput(ar1);
            return ar1;
        }
    
        public void screeOutput() {
            for (Comparable x : temp1) {
                System.out.println(x + " ");
            }
            System.out.println();
        }
    
        public void screenOutput(ArrayList<Comparable> temp) {
            for (Comparable x : temp) {
                System.out.println(x + " ");
            }
            System.out.println();
        }
    
        public void rMerge(ArrayList<Comparable> rList) {
            rMerge(rList, 0, rList.size() - 1);
        }
    
        public void rMerge(ArrayList<Comparable> rList, int first, int last) {
    
            int mid = 0;
            if (first >= last) {
                System.out.println("no error yet");
            } else {
                mid = (first + last) / 2;
                rMerge(rList, first, mid);
                rMerge(rList, mid + 1, last);
                merge(rList, first, mid, last);
            }
        }
    
        public void merge(ArrayList<Comparable> a, int first, int mid, int last) {
            int i, j, k, m;
    
            i = first;
            j = mid + 1;
            k = first;
    
            ArrayList<Comparable> tempList = new ArrayList<>();
    
            // compare two divided parts
            while (i <= mid && j <= last) {
                if (a.get(i).compareTo(a.get(j)) < 1) {
                    tempList.add(a.get(i));
                    i++;
                } else {
                    tempList.add(a.get(j));
                    j++;
                }
                k++;
            }
    
            if (i > mid) {
                for (m = j; m <= last; m++) {
                    tempList.add(a.get(m));
                    k++;
                }
            } else {
                for (m = i; m <= mid; m++) {
                    tempList.add(a.get(m));
                    k++;
                }
            }
    
            for (i = 0, j = first; i < tempList.size(); i++, j++) {
                a.set(j, tempList.get(i));
            }
    
        }
    
    }