java中的算法比较:测试程序不起作用

时间:2013-04-18 16:23:26

标签: java algorithm quicksort hybrid

我正在尝试比较QuickSort的java实现及其混合版本的执行(对于小于整数k的分区使用InsertionSort)。我编写了一个测试类来分析某些值的算法行为ok k(1< = k< = 25)。对于k的每个值,类比较两种算法的输入数组的不同大小。

我不能为数组大小的某些值运行程序,例如对于大于4000的值。执行达到一些不同的值然后冻结,一段时间后它将完成但我没有计算的输出。 (我正在使用eclipse)。
那可能是什么问题?我希望对两个算法进行比较,数组大小从10到10000(至少)。
代码如下:

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) {

    }
}

}

算法类:

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;
}
}

3 个答案:

答案 0 :(得分:0)

您对Partition的实施不正确。考虑下面的小测试(为方便起见,我做了Partition static

两个while循环都不会被执行,因为A[i] == A[j] == pivot。而且,i<j,因此两个元素将被交换,从而产生完全相同的数组。因此,外部while循环变为无限。

对于第一个和最后一个元素相同的任何数组,都会出现同样的问题。

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;
            }
        }
    }
}

答案 1 :(得分:0)

您是否尝试增加代码的内存设置以在eclipse中运行。 您可能会发现此Setting memory of Java programs that runs from Eclipse有用。

答案 2 :(得分:0)

一些提示/可能的解决方案?:

我没有阅读您的QuickSort或HybridSort的实现,但我认为它们是正确的。

  1. 如果您要比较两种算法的性能,您最应该将它们的性能与压缩输入进行比较。目前你正在生成两个随机的arrys(尽管大小相同)。这不一定是一个准确的测试,因为我可以很容易地找到一个测试用例,如果随机生成器出现在你身上,一个算法将胜过另一个算法。

  2. 根据我的说法,你比较两种算法的逻辑有点奇怪和不正确。为什么要比较时间串的长度?根据你的逻辑,1与9相同,1,000,000,000与9,999,999,999相同,这显然是不正确的。一种算法几乎比另一种算法快10倍。

  3. 此外,没有输出的一个原因可能是你只在hybridsort优于quicksort时输出,而不是相反。我确信还有其他原因,但这可能是一个容易理解的原因(如果你的实现不正确)。

    我注意到你关闭了你的输出流,因为这是没有输出的一个非常常见的原因。但是,您应该在try-catch的finally部分关闭蒸汽,因为它们会保证关闭。您可能会收到IOException,在您的情况下,这也不会关闭输出组,从而导致文件中没有输出。

  4. 以下是我要进行任何比较测试的示例结构。它具有足够的输出,易于阅读和调试,可以确定哪种算法性能更好。这只是一个建议。

    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();
        }
      }
    }