Вопрос

I'm trying to compare the execution of the java implementation of QuickSort and its hybrid version (using InsertionSort for those partitions which are smaller than an integer k). I wrote a test class to analyze the behaviour of the algorithms for some values ok k (1 <= k <= 25). For each value of k the class compares for different sizes of the input array the two algorithms.

I can't run the program for some values of the size of the array, for instance for values greater than 4000. The execution reach some different values and then freeze, after a while it will finish but I have no output of the computation. (I'm using eclipse).
What could be the problem? I wish to perform the comparation of the two algoritms for an array size from 10 to 10000 (at least).
The code is listed below:

public class Main {

private static final int MAX_K = 25;
private static final int MAX_SIZE = 4500;
private static final int ADD_SIZE = 100;
private static int size = 10;

private static QuickSort qSort;
private static HybridSort hSort;

private static void initArray(int[] A) {
    Random rand = new Random();
    for (int i = 0; i < A.length; i++) {
        // A[i] = (int)(Math.random()*100000);
        A[i] = rand.nextInt();

    }
}

private static int[] A = new int[10];
private static int[] B = new int[10];

public static void main(String[] args) {

    try {

        FileWriter fstream = new FileWriter("out.txt");
        BufferedWriter out = new BufferedWriter(fstream);
        out.write("Init file");

        qSort = new QuickSort();
        hSort = new HybridSort();

        /************************************************/
        /* Comparison */
        /************************************************/

        for (int i = 1; i <= MAX_K; i++) {
            hSort.setK(i);

            int p = 0;
            for (int j = size; j <= MAX_SIZE; j = j + ADD_SIZE) {

                A = new int[j];
                B = new int[j];
                initArray(A);
                initArray(B);

                long sTime = System.nanoTime();
                qSort.quickSort(A, 0, A.length - 1);
                long qDuration = System.nanoTime() - sTime;

                sTime = System.nanoTime();
                hSort.hybridSort(B, 0, B.length - 1);
                long hDuration = System.nanoTime() - sTime;

                out.append(/* "\nA: " +printArray(A)+ */"K: " + i + " A["
                        + j + "]\tQ = " + qDuration + " H = " + hDuration
                        + "\n");

                String h = Long.toString(hDuration);
                String q = Long.toString(qDuration);

                if (h.length() < q.length()) {
                    p++;
                    out.append("\t#OUTPERM for K: "
                            + i
                            + "\t\t"
                            + hDuration
                            + "\t\t < \t\t "
                            + qDuration
                            + "\t\t\t\t| A[]\t\t"
                            + A.length
                            + ((q.length() - h.length()) == 2 ? "\t Magn. 2"
                                    : "") + "\n");
                }
            }
            if (p > 0)
                out.append("#P= " + p + " for K= " + i + "\n\n");
        }
        out.append("Close file");
        out.close();
    } catch (IOException e) {

    }
}

}

The algorithm classes:

public class QuickSort {


public void quickSort(int[] A, int left, int right){
    if (left < right) {
        int m = Partition(A, left, right);
        quickSort(A, left, m-1);
        quickSort(A, m, right);
    }
}


private int Partition(int[] A, int left, int right){
    int pivot = A[right];
    int i = left;
    int j = right;

    while (true) {
        while ( (A[j] > pivot)) {
            j--;
        }
        while ((A[i] < pivot)) {
            i++;
        }
        if (i < j){
            int swap = A[j];
            A[j] = A[i];
            A[i] = swap;
        }else{
            return i;
        }
    }
}

}


public class HybridSort {

int k;
int m;
InsertionSort iSort;

public HybridSort() {
    k = 3;
    iSort = new InsertionSort();
}

public void hybridSort(int[] A, int left, int right) {
    if (left < right) {
        if ((right - left) < k) {
                                    iSort.sort(A,left,right);
        } else {                
            m = Partition(A, left, right);
            hybridSort(A, left, m - 1);
            hybridSort(A, m, right);
        }
    }
}

private int Partition(int[] A, int left, int right) {
    int pivot = A[right];
    int i = left;
    int j = right;

    while (true) {
        while ((A[j] > pivot) && (j >= 0)) {
            j--;
        }
        while ((A[i] < pivot) && (i < A.length)) {
            i++;
        }
        if (i < j) {
            int swap = A[j];
            A[j] = A[i];
            A[i] = swap;
        } else {
            return i;
        }
    }
}


public void setK(int k) {
    this.k = k;
}
}
Это было полезно?

Решение

Your implementation of Partition is not correct. Consider the small test below (I made Partition static for my convenience).

Both while loops won't be executed, because A[i] == A[j] == pivot. Moreover, i<j, so the two elements will be swapped, resulting in exactly the same array. Therefore, the outer while loop becomes infinite.

The same problem occurs for any array for which the first and last element are the same.

public class Test {
    public static void main(String[] args) {
        int[] A = {1, 1};
        Partition(A, 0, 1);
    }

    private static int Partition(int[] A, int left, int right){
        int pivot = A[right];
        int i = left;
        int j = right;

        while (true) {
            while ( (A[j] > pivot)) {
                j--;
            }
            while ((A[i] < pivot)) {
                i++;
            }
            if (i < j){
                int swap = A[j];
                A[j] = A[i];
                A[i] = swap;
            }else{
                return i;
            }
        }
    }
}

Другие советы

Have you tried increasing memory settings for your code to run in eclipse. You may find this Setting memory of Java programs that runs from Eclipse helpful.

Some tips / possible solution?:

I haven't read your implementation of QuickSort or HybridSort but I am assuming they are correct.

  1. If you are comparing the performance of two algorithms you should most definitely compare their performance to indentical inputs. Currently you are generating two random arrys (albeit of the same size). This isn't necessarily going to be an accurate test as I can easily find a test case where one algorithm will outperform the other if the random generator is out to troll you.

  2. Your logic for comparing the two algorithms is a bit weird and incorrect according to me. Why do you compare the lengths of the strings of the times? according to your logic 1 is the same as 9 and 1,000,000,000 is the same as 9,999,999,999 which is clearly incorrect. One algorithm is almost 10 times faster than the other.

  3. Moreover, one reason for no output might be the reason that you are only outputing when hybridsort is better than quicksort and not the other way around. I am sure there are other reasons as well but this could be one easily noticable reason (if your implementations are incorrect).

    I do notice that you close your outputstream which is good as that is a very common reason why there is no output. You should however, close steams in the finally section of the try-catch as then they are guaranteed to close. You could be getting an IOException and in your case this would also not close the outputsteam and consequently lead to no ouput in your file.

Here is a sample structure that I would follow for doing any comparitive testing. It is easy to read and easy to debug with enough output for you to figure out which algorithm performs better. This is merely a suggestion.

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Random;

public class Tester {

  private static int[] initArray(int size) {
    Random rand = new Random();
    int[] arr = new int[size];
    for (int i = 0; i < arr.length; i++) {
      arr[i] = rand.nextInt();
    }
    return arr;
  }

  public static void main(String[] args) {
    final int MAX_ITERATIONS = 25;
    final int INITIAL_ARRAY_SIZE = 10;
    final int MAX_ARRAY_SIZE = 4500;
    final int ARRAY_SIZE_INCREMENT = 100;

    long start;
    int[] score = null;

    PrintWriter out = null;
    try {
      out = new PrintWriter(new FileOutputStream("out.txt"));
      for (int arraySize = INITIAL_ARRAY_SIZE; arraySize <= MAX_ARRAY_SIZE; arraySize += ARRAY_SIZE_INCREMENT) {
        // score[0] is for quickSort and score[1] is for hybridSort
        score = new int[2];
        for (int iteration = 0; iteration < MAX_ITERATIONS; iteration++) {
          int[] testArray = initArray(arraySize);
          int[] testArrayCopy = new int[arraySize];
          System.arraycopy(testArray, 0, testArrayCopy, 0, arraySize);

          start = System.nanoTime();
          // Do quicksort here using testArray
          long qSortfinish = System.nanoTime() - start;

          System.arraycopy(testArray, 0, testArrayCopy, 0, arraySize);
          start = System.nanoTime();
          // Do hybridsort here using testArrayCopy
          long hybridSortfinish = System.nanoTime() - start;

          // Keep score
          if (qSortfinish < hybridSortfinish)
            score[0]++;
          else if (qSortfinish > hybridSortfinish) {
            score[1]++;
          } else {
            score[0]++;
            score[1]++;
          }
        }
        out.println("Array Size: " + arraySize + " QuickSort: " + score[0] + " HybridSort: " + score[1]);
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } finally {
      if (out != null)
        out.close();
    }
  }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top