简体   繁体   中英

Stackoverflow error in my quicksort implementation

I have extended my codes with having an additional insertion sort algorithm to be chosen by giving the boolean value insertionSort either true or false when constructing a class instance. But when I execute my codes, then i get Stackoverflow error. The codes are as follows:

    import java.util.Random;

    /**
     * Write a description of class QuickSort1 here.
     * 
     * @author (your name) 
     * @version (a version number or a date)
     */
    public class QuickSort1 implements IntSorter
    {
        private int[] v;
        private Random randomGenerator;
        private boolean insertionSort;
        private InsertionSort insertionSorter;

        public QuickSort1(boolean useInsertionSort)
        {
            randomGenerator = new Random();
            insertionSort = useInsertionSort;
            if(insertionSort)
                insertionSorter = new InsertionSort();
        }

        public void sort(int[] v)
        {
            this.v = v;
            if(this.v.length > 0) {
                quickSort(this.v, 0, this.v.length-1);
            }
            else {
                return;
            }
        }

        private void quickSort(int[] v, int first, int last)
        {
            final int startInsertion = 20;
            int First = first;
            int Last = last;
            int pivot = v[randomGenerator.nextInt(v.length)];        

            if(Last-First<2 && !insertionSort)
                return;
            else if(insertionSort) {
                if(pivot >= Last-startInsertion)
                    v = insertionSorter.sort(v);
            }
            else {
                while(First <= Last) {
                    while(v[First] < pivot) {
                        First++;
                    }
                    while(v[Last] > pivot) {
                        Last--;
                        if(Last==0)
                            break;
                    }
                    if(First<=Last) {
                        int temp = v[First];
                        v[First] = v[Last];
                        v[Last] = temp;
                        First++;
                        Last--;
                    }
                }

                if(first < Last

)
                quickSort(v, first, Last);
            if(First < last)
                quickSort(v, First, last);
        }        
    }

    public boolean getInfo()
    {
        return insertionSort;
    }
}

For the alternative insertion algorithm I have implemented a simple class with the following codes:

/**
 * Write a description of class InsertionSort here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class InsertionSort
{
    int[] v;

    /**
     * Constructor for objects of class InsertionSort
     */
    public InsertionSort()
    {
    }

    public int[] sort(int[] v)
    {
        for(int i=1;i<v.length;i++) {
            int temp = v[i];
            int j;
            for(j=i-1;j>=0 && temp<v[j];j--) {
                v[j+1] = v[j];
            }
            v[j+1] = temp;
        }
        return v;
    }
}

The error messages I now get for executing this algorithm for arrays with the size of 10.000-100.000 elements are the following:

java.lang.StackOverflowError
    at java.util.Random.nextInt(Random.java:307)
    at QuickSort1.quickSort(QuickSort1.java:40)
    at QuickSort1.quickSort(QuickSort1.java:68)

The error at line 68 gets reapeted in the terminal a lot of times and it indicates on the first recursive call of the quickSort method. The line 40 indicates on the line where the pivot element gets decided by Java's randomizing int generator.

I have a strong feeling that this algorithm perhaps cannot be better than it is now since for bigger number of elements, the stack will get empty during the execution for great numbers of elements to be sorted and therefore I perhaps get that StackOverflowError. But perhaps you have another opinion about this problem?

Thanks in advance for helping me out with this :D

So here we go. I tried your code with a array size of 1,000,000, there 2GB RAM where not enough. So finally the answer will not be satisfying for you, but to point that problem out could be a nightlong program. But I think Stefan Mandel striked the nerve, so if you are interested, feel free to investigate in this direction. But now I won't let you go like that. I did your homework. This is working even with the regular heap size. Here is a example how to increase the heap. You'll only need the -Xmx1024 to increase the RAM to 1 GB.

public class QuickFooBar {

public static void main(String[] args) {
    Random random = new Random();
    int[] arr = new int[1000000];
    for (int i = 0; i < arr.length; ++i) {
        arr[i] = random.nextInt(1000000);
    }

    QuickSort1 test;
    test = new QuickSort1(false);
    test.setV(arr);
    test.quickSort(0, arr.length - 1);
    arr = test.getV();

    for (int i = 0; i < arr.length; ++i) {
        System.out.println(arr[i] + ", ");
    }
}

}

public class QuickSort1 {

private int[] arr;
private final boolean insertionSort;


public QuickSort1(final boolean insertionSort) {
    this.insertionSort = insertionSort;
}

public void quickSort(int left, int right) {
    final int startInsertion = 20;
    if (insertionSort) {
        if (((left + right) / 2) >= right - startInsertion) {
            arr = new InsertionSort().sort(arr);
            return;
        }
    }
    int index = partition(left, right);
    if (left < index - 1) {
        quickSort(left, index - 1);
    }
    if (index < right) {
        quickSort(index, right);
    }
}

private int partition(int left, int right) {
    int i = left, j = right;
    int tmp;
    int pivot = arr[new Random(right).nextInt()];
    while (i <= j) {
        while (arr[i] < pivot) {
            i++;
        }
        while (arr[j] > pivot) {
            j--;
        }
        if (i <= j) {
            tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
            i++;
            j--;
        }
    };
    return i;
}

public boolean getInfo() {
    return insertionSort;
}

public int[] getV() {
    return arr;
}

public void setV(int[] v) {
    this.arr = v;
}

}

public class InsertionSort {

public int[] sort(int[] v) {
    for (int i = 1; i < v.length; ++i) {
        int temp = v[i];
        int j;
        for (j = i - 1; j >= 0 && temp < v[j]; j--) {
            v[j + 1] = v[j];
        }
        v[j + 1] = temp;
    }
    return v;
}

}

    public int[] sort(int[] v) {
    for (int i = 1; i < v.length; ++i) {
        int temp = v[i];
        int j;
        for (j = i - 1; j >= 0 && temp < v[j]; j--) {
            v[j + 1] = v[j];
        }
        v[j + 1] = temp;
    }
    return v;
}

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM