基准排序算法 Java;平均 运行 次不正确

Benchmarking Sorting Algorithms Java; Average Run Times are incorrect

虽然我知道以下基准测试方法并不理想,但我正在研究基准排序算法以帮助更好地理解算法和数据结构。

我想列出“大”n 500000 和小“n”大小数组 50 的平均 运行 次,但我的平均值总是在增加。

我不确定哪里出错了:

    public class BenchmarkingAlgorithms
    {
        public static void main(String[] args)
        {
            int[] largeUnsortedArray = largeArrayWithRandomInts(500000);

        
      
        bubbleSort(largeUnsortedArray);
        
        selectionSort(largeUnsortedArray);
        insertionSort(largeUnsortedArray);
        benchmarkQuickSort(largeUnsortedArray);
        benchmarkMergeSort(largeUnsortedArray);
        
        
        int[] smallUnsortedArray = smallArrayWithRandomInts(50);

        bubbleSort(smallUnsortedArray);
        selectionSort(smallUnsortedArray);
        insertionSort(smallUnsortedArray);
        benchmarkQuickSort(smallUnsortedArray);
        benchmarkMergeSort(smallUnsortedArray);
    }

    /**
     * Sorting an array of ints in ascending order using bubbleSort
     * Best-Case Complexity: O(n), Average Complexity: O(n^2), Worst-Case Complexity: O(n^2)
     * O(n) is achieved in Best-Case (already sorted array) using the alreadySorted flag
     * @param array
     * @return
     */
    static int[] bubbleSort(int[] array)
    {
         int bubbleSortTime[] = new int[500];
          int x, y;
          for (x = 0; x< 500; x++) {
              
          
        int temp;
        boolean alreadySorted = true;
        long start = System.nanoTime();
       
        {
            for (int i = 0; i < array.length; i++)
        {
          

            for (int j = 0; j < array.length - 1; j++)
            {

                if (array[j] > array[j + 1])
                {
                    alreadySorted = false;
                    temp = array[j + 1];
                    array[j + 1] = array[j];
                    array[j] = temp;
                }
                
            }
            if (alreadySorted == true)
            {
                break;
            }
            
        }
            long end = System.nanoTime();
            
            long bubbleSortRunTime = end - start;
            
            bubbleSortTime[x] = (int) bubbleSortRunTime;
            x++;
            

        }
        // getting array length
        int length = bubbleSortTime.length;
 
        // default sum value.
        int sum = 0;
 
        // sum of all values in array using for loop
        for (int i = 0; i < bubbleSortTime.length; i++) {
            sum += bubbleSortTime[i];
        }
 
        double average = sum / length;
         
        System.out.println("Average of array : "+average + " nano seconds.");
 
    }
        
          

        return array;
          
    
    }

    /**
     * Sorting an array of ints in ascending order using selectionSort
     * Best-Case Complexity: O(n^2), Average Complexity: O(n^2), Worst-Case Complexity: O(n^2)
     * @param array
     * @return
     */
    static int[] selectionSort(int[] array)
    {
        
         int selectionSortTime[] = new int[500];
         int x, y;
         for (x = 0; x< 500; x++) {
          
        int min;
        int pos = 0;
        long start = System.nanoTime();
     
        {
            for (int i = 0; i < array.length - 1; i++)
            {
               
                min = array[i];
                for (int j = i + 1; j < array.length; j++)
                {
                    if (array[j] < min)
                    {
                        min = array[j];
                        pos = j;
                    }
                }
                array[pos] = array[i];
                array[i] = min;
            }
           

        }
        long end = System.nanoTime();
        
        long selectionSortRunTime = end - start;
        
        selectionSortTime[x] = (int) selectionSortRunTime;
        x++;
        

    
    // getting array length
    int length = selectionSortTime.length;

    // default sum value.
    int sum = 0;

    // sum of all values in array using for loop
    for (int i = 0; i < selectionSortTime.length; i++) {
        sum += selectionSortTime[i];
    }

    double average = sum / length;
     
    System.out.println("Average of array : "+average + " nano seconds.");

}
    
        
        return array;
    }

    /**
     * Sorting an array of ints in ascending order using insertionSort
     * Best-Case Complexity: O(n), Average Complexity: O(n^2), Worst-Case Complexity: O(n^2)
     * @param array
     * @return
     */
    static int[] insertionSort(int[] array)
    {
        
        int insertionSortTime[] = new int[500];
      int x, y;
        for (x = 0; x< 500; x++) {
        long start = System.nanoTime();
        int j;

       
        {
            for (int i = 1; i < array.length; i++)
            {
             

                int key = array[i];

                for (j = i - 1; (j >= 0) && (key < array[j]); j--)
                {
                    array[j + 1] = array[j];
                }
                array[j + 1] = key;
            }
          

        }
        long end = System.nanoTime();
    long insertionSortRunTime = end - start;
        
        insertionSortTime[x] = (int) insertionSortRunTime;
        x++;
        

    
    // getting array length
    int length = insertionSortTime.length;

    // default sum value.
    int sum = 0;

    // sum of all values in array using for loop
    for (int i = 0; i < insertionSortTime.length; i++) {
        sum += insertionSortTime[i];
    }

    double average = sum / length;
     
    System.out.println("Average of array : "+average + " nano seconds.");

}
        

        return array;
    }

    /**
     * Sorting an array of ints in ascending order using quickSort
     * Best-Case Complexity: O(n log(n)), Average Complexity: O(n log(n)), Worst-Case Complexity: O(n^2))
     * @param array
     * @return
     */
    static void quickSort(int[] array, int low, int high)
    {
        
        int pivot = array[low + ((high - low) / 2)];
        int i = low;
        int j = high;


            while (i <= j)
            {

                while (array[i] < pivot)
                {
                    i++;
                }
                while (array[j] > pivot)
                {
                    j--;
                }
                if (i <= j)
                {
                    int temp = array[i];
                    array[i] = array[j];
                    array[j] = temp;
                    i++;
                    j--;
                }
            }

            if (low < j)
            {
                quickSort(array, low, j);
            }

            if (i < high)
            {
                quickSort(array, i, high);
            }
        }

    /**
     * Helping method to benchmark quick sort's execution time
     * @param array
     */
    static void benchmarkQuickSort(int[] array)
    { 
        int quickSortTime[] = new int[500];
          int x, y;
          for (x = 0; x< 500; x++) {
        long start = System.nanoTime();
        quickSort(array, 0, array.length - 1);
        long end = System.nanoTime();
        long quickSortRunTime = end - start;
        
        quickSortTime[x] = (int) quickSortRunTime;
        x++;
        

    
    // getting array length
    int length = quickSortTime.length;

    // default sum value.
    int sum = 0;

    // sum of all values in array using for loop
    for (int i = 0; i < quickSortTime.length; i++) {
        sum += quickSortTime[i];
    }

    double average = sum / length;
     
    System.out.println("Average of array : "+average + " nano seconds.");

}
        
    }

    /**
     * Sorting an array of ints in ascending order using mergeSort
     * Best-Case Complexity: O(n log(n)), Average Complexity: O(n log(n)), Worst-Case Complexity: O(n log(n)))
     * @param array
     * @return
     */
    public static int[] mergeSort(int[] array)
    {
        if (array.length == 1)
        {
            return array;
        }

        int[] array1 = new int[(array.length/2)];
        int[] array2 = new int[(array.length-array1.length)];

        System.arraycopy(array, 0, array1, 0, array1.length);
        System.arraycopy(array, array1.length, array2, 0, array2.length);

        mergeSort(array1);
        mergeSort(array2);

        merge(array1, array2, array);
        return array;
    }

    /**
     * Merges 2 sorted arrays of ints
     * @param array1
     * @param array2
     * @param mergedArray
     * @return
     */
    static void merge(int[] array1, int[] array2, int[] mergedArray)
    {
        int array1Index = 0;
        int array2Index = 0;
        int pos = 0;
        while ((array1Index < array1.length) && (array2Index < array2.length))
        {
            if (array1[array1Index] < array2[array2Index])
            {
                mergedArray[pos] = array1[array1Index];
                array1Index++;
                pos++;
            } else
            {
                mergedArray[pos] = array2[array2Index];
                array2Index++;
                pos++;
            }
        }

        if (array1Index < array2Index)
        {
            System.arraycopy(array1, array1Index, mergedArray, pos, array1.length - array1Index);
        }
        else if (array2Index < array1Index) ;
        {
            System.arraycopy(array2, array2Index, mergedArray, pos, array2.length - array2Index);
        }
    }

    /**
     * Helping method to benchmark merge sort's execution time
     * @param array
     */
    static void benchmarkMergeSort(int[] array)
    {
        int mergeSortTime[] = new int[500];
      int x, y;
        for (x = 0; x< 500; x++) {
        long start = System.nanoTime();
        mergeSort(array);
        long end = System.nanoTime();
  long quickSortRunTime = end - start;
        
        mergeSortTime[x] = (int) quickSortRunTime;
        x++;
        

    
    // getting array length
    int length = mergeSortTime.length;

    // default sum value.
    int sum = 0;

    // sum of all values in array using for loop
    for (int i = 0; i < mergeSortTime.length; i++) {
        sum += mergeSortTime[i];
    }

    double average = sum / length;
     
    System.out.println("Average of array : "+average + " nano seconds.");
        }

}

    /**
     * Creates and returns an array with random ints
     * @param size the size of the array to be created
     * @return
     */
    static int[] largeArrayWithRandomInts(int size)
    {
        int[] largeArray = new int[size];

        for (int i = 0; i < size; i++)
        {
            largeArray[i] = (int) (Math.random() * Math.random() * 500000);
        }
        return largeArray;
    }
    
    static int[] smallArrayWithRandomInts(int size)
    {
        int[] smallArray = new int[size];

        for (int i = 0; i < size; i++)
        {
            smallArray[i] = (int) (Math.random() * Math.random() * 50);
        }
        return smallArray;
    }

    /**
     * Prints the elements of  one dimensional array of type int
     * @param array
     */
    static void printArray(int[] array)
    {
        for (int i = 0; i < array.length; i++)
        {
            System.out.print(array[i] + " ");
        }
        System.out.println();
    }

}

我很感激任何见解。随时准备学习新事物。

您的方法中有多处出错。

  1. 您正在通过取 bubbleSortTime 中 500 个元素的平均值来计算和打印中间时间。对于第一个 运行,而不是除以 bubbleSortTime.length(即 500),您应该除以 x + 1 以获得您完成的 运行 的平均值到目前为止。
  2. 您分别为每个 运行 计时,由于 System.nanoTime() 的工作方式,四舍五入到大约 50 纳秒(参见 javadoc)。你应该做的是将开始时间存储到一个变量,然后 运行 你想要在一个循环中计时 X 次的代码(100-1000 次通常就足够了,更多 运行s 会给出一个更精确的结果),然后记录结束时间,最后将经过的时间除以X,得到定时代码的平均运行时间。
  3. 在开始为您的代码计时之前,您应该至少 运行 计时代码一次。这将导致加载所有 类 和所需的系统库,这可能是一次稍微慢一点的操作。