如何提高班级的速度?

时间:2016-10-27 22:17:10

标签: java

我正在运行这个,我被告知它运行速度不够快。什么是提高这个运行类的速度的好方法?我猜我需要改变我的嵌套while循环。这是我唯一能想到的。 if语句应该都是线性的......

import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;

public class QSortLab {

    static int findpivot(Comparable[] A, int i, int j) {
        return (i + j) / 2;
    }

    static <E> void swap(E[] A, int p1, int p2) {
        E temp = A[p1];
        A[p1] = A[p2];
        A[p2] = temp;
    }

    static void quicksort(Comparable[] A, int i, int j) { // Quicksort
        int pivotindex = findpivot(A, i, j);  // Pick a pivot
        swap(A, pivotindex, j);               // Stick pivot at end
        int k = partition(A, i, j-1, A[j]);
        swap(A, k, j);                        // Put pivot in place
        if ((k-i) > 1) quicksort(A, i, k-1);  // Sort left partition
        if ((j-k) > 1) quicksort(A, k+1, j);  // Sort right partition
    }

    static int partition(Comparable[] A, int left, int right, Comparable pivot) {
        while (left <= right) { // Move bounds inward until they meet
            while (A[left].compareTo(pivot) < 0) left++;
            while ((right >= left) && (A[right].compareTo(pivot) >= 0)) right--;
            if (right > left) swap(A, left, right); // Swap out-of-place values
        }
        return left;            // Return first position in right partition
    }
}

2 个答案:

答案 0 :(得分:1)

您是什么意思需要更改嵌套的while循环?快速排序由这些功能定义。删除不会正常运行。

至于优化,默认情况下应该知道primitives vs objects往往不同。例如。 primitives on stack/heap保持堆叠小而且heap使用refs able to be on stack存储对象。

所以让我们测试一些东西

  • 原始快速排序(from here
  • 整数快速排序(与上面相同的代码,但使用Integer类)
  • 您的原始发布代码
  • 您的原始发布代码(带有多个修改)

这是我使用的整个代码。

import java.util.Random;

public class App {

    public static final int ARR_SIZE = 1000;
    public static final int TEST_ITERS = 10000;
    public static Random RANDOM = new Random();

    public static void main(String[] args) {
        int[] a = new int[ARR_SIZE];
        Integer[] b = new Integer[ARR_SIZE];
        Integer[] c = new Integer[ARR_SIZE];
        Integer[] d = new Integer[ARR_SIZE];

        long sum = 0, start = 0, end = 0;
        for (int i = 0; i < TEST_ITERS; ++i) {
            for (int j = 0; j < ARR_SIZE; ++j)
                a[j] = RANDOM.nextInt();
            start = System.nanoTime();
            quickSort(a, 0, a.length - 1);
            end = System.nanoTime();
            sum += (end - start);
        }
        System.out.println((sum / TEST_ITERS) + " nano, qs avg - 'int'");

        sum = 0;
        for (int i = 0; i < TEST_ITERS; ++i) {
            for (int j = 0; j < ARR_SIZE; ++j)
                b[j] = RANDOM.nextInt();
            start = System.nanoTime();
            quickSort(b, 0, b.length - 1);
            end = System.nanoTime();
            sum += (end - start);
        }
        System.out.println((sum / TEST_ITERS) + " nano, qs avg - 'Integer'");

        sum = 0;
        for (int i = 0; i < TEST_ITERS; ++i) {
            for (int j = 0; j < ARR_SIZE; ++j)
                c[j] = RANDOM.nextInt();
            start = System.nanoTime();
            quicksort(c, 0, c.length - 1);
            end = System.nanoTime();
            sum += (end - start);
        }
        System.out.println((sum / TEST_ITERS) + " nano, qs avg - 'Comparable' (SO user code)");

        sum = 0;
        for (int i = 0; i < TEST_ITERS; ++i) {
            for (int j = 0; j < ARR_SIZE; ++j)
                d[j] = RANDOM.nextInt();
            start = System.nanoTime();
            qs_quicksort(d, 0, d.length - 1);
            end = System.nanoTime();
            sum += (end - start);
        }
        System.out.println((sum / TEST_ITERS) + " nano, qs avg - 'Comparable' (SO user code - edit)");

        for (int i = 0; i < ARR_SIZE; ++i) {
            final int n = RANDOM.nextInt();
            a[i] = n;
            b[i] = n;
            c[i] = n;
            d[i] = n;
        }
        quickSort(a, 0, a.length - 1);
        Integer[] aConv = new Integer[ARR_SIZE];
        for (int i = 0; i < ARR_SIZE; ++i)
            aConv[i] = a[i];
        quickSort(b, 0, b.length - 1);
        quicksort(c, 0, c.length - 1);
        qs_quicksort(d, 0, d.length - 1);

        isSorted(new Integer[][] { aConv, b, c, d });
        System.out.println("All properly sorted");
    }

    public static void isSorted(Integer[][] arrays) {
        if (arrays.length != 4) {
            System.out.println("error sorting, input arr len");
            return;
        }
        for (int i = 0; i < ARR_SIZE; ++i) {
            int val1 = arrays[0][i].compareTo(arrays[1][i]);
            int val2 = arrays[1][i].compareTo(arrays[2][i]);
            int val3 = arrays[2][i].compareTo(arrays[3][i]);
            if (val1 != 0 || val2 != 0 || val3 != 00) {
                System.out.printf("Error [i = %d]: a = %d, b = %d, c = %d", i, arrays[0][i], arrays[1][i], arrays[2][i], arrays[3][i]);
                break;
            }
        }
    }

    public static int partition(int arr[], int left, int right) {
        int i = left, j = right;
        int tmp;
        int pivot = arr[(left + right) / 2];
        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 static void quickSort(int arr[], int left, int right) {
        int index = partition(arr, left, right);
        if (left < index - 1)
            quickSort(arr, left, index - 1);
        if (index < right)
            quickSort(arr, index, right);
    }

    public static int partition(Integer[] arr, int left, int right) {
        int i = left, j = right;
        Integer pivot = arr[(left + right) / 2];
        while (i <= j) {
            while (arr[i].compareTo(pivot) < 0)
                i++;
            while (arr[j].compareTo(pivot) > 0)
                j--;
            if (i <= j) {
                Integer temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
                i++;
                j--;
            }
        }
        return i;
    }

    public static void quickSort(Integer[] arr, int left, int right) {
        int index = partition(arr, left, right);
        if (left < index - 1)
            quickSort(arr, left, index - 1);
        if (index < right)
            quickSort(arr, index, right);
    }

    static int findpivot(Comparable[] A, int i, int j)
    {
        return (i+j)/2;
    }

    static <E> void swap(E[] A, int p1, int p2) {
        E temp = A[p1];
        A[p1] = A[p2];
        A[p2] = temp;
    }


    static void quicksort(Comparable[] A, int i, int j) { // Quicksort
        int pivotindex = findpivot(A, i, j);  // Pick a pivot
        swap(A, pivotindex, j);               // Stick pivot at end
        int k = partition(A, i, j-1, A[j]);
        swap(A, k, j);                        // Put pivot in place
        if ((k-i) > 1) quicksort(A, i, k-1);  // Sort left partition
        if ((j-k) > 1) quicksort(A, k+1, j);  // Sort right partition
    }

    static int partition(Comparable[] A, int left, int right, Comparable pivot) {
        while (left <= right) { // Move bounds inward until they meet
            while (A[left].compareTo(pivot) < 0) left++;
            while ((right >= left) && (A[right].compareTo(pivot) >= 0)) right--;
            if (right > left) swap(A, left, right); // Swap out-of-place values
        }
        return left;            // Return first position in right partition
    }

    static <E> void qs_swap(E[] A, int p1, int p2) {
        E temp = A[p1];
        A[p1] = A[p2];
        A[p2] = temp;
    }

    static void qs_quicksort(Comparable[] A, int i, int j) { // Quicksort
        int pivotindex = (i+j)/2;
        qs_swap(A, pivotindex, j);               // Stick pivot at end
        int k = qs_partition(A, i, j-1, A[j]);
        qs_swap(A, k, j);                        // Put pivot in place
        if ((k-i) > 1) qs_quicksort(A, i, k-1);  // Sort left partition
        if ((j-k) > 1) qs_quicksort(A, k+1, j);  // Sort right partition
    }

    static int qs_partition(Comparable[] A, int left, int right, Comparable pivot) {
        while (left <= right) { // Move bounds inward until they meet
            while (A[left].compareTo(pivot) < 0) left++;
            while ((right >= left) && (A[right].compareTo(pivot) >= 0)) right--;
            if (right > left) { qs_swap(A, left, right); // Swap out-of-place values
            left++; right--;}
        }
        return left;            // Return first position in right partition
    }
}

这会产生输出:

56910 nano, qs avg - 'int'
69498 nano, qs avg - 'Integer'
76762 nano, qs avg - 'Comparable' (SO user code)
71846 nano, qs avg - 'Comparable' (SO user code - edit)
All properly sorted

现在,分解结果

&#39; int&#39; vs&#39;整数&#39;简单地使用基元和非基元时显示出很大的差异(我确信在代码中的某些点可能有装箱,但希望不是在关键位置;) - 如果是这样,请编辑它)。 &#39; int&#39; vs&#39;整数&#39;使用相同的代码,除了&#39; int&#39; &#39;整数&#39 ;.请参阅此比较中使用的以下四种方法签名,&#39; int&#39;

public static int partition(int arr[], int left, int right)
public static void quickSort(int arr[], int left, int right)

和&#39;整数&#39;

public static int partition(Integer[] arr, int left, int right)
public static void quickSort(Integer[] arr, int left, int right)

分别

然后是与您发布的原始代码相关的方法签名,

static int findpivot(Comparable[] A, int i, int j)
static <E> void swap(E[] A, int p1, int p2)
static void quicksort(Comparable[] A, int i, int j)
static int partition(Comparable[] A, int left, int right, Comparable pivot)

和修改过的,

static <E> void qs_swap(E[] A, int p1, int p2)
static void qs_quicksort(Comparable[] A, int i, int j)
static int qs_partition(Comparable[] A, int left, int right, Comparable pivot)

如您所见,在修改后的代码中,findpivot被直接删除并替换为quicksort中的调用点。此外,分区方法分别获得了左右计数器。 left++; right--;

最后,为了确保quicksort的这4个变体实际上只做了唯一的目的,排序,我添加了一个方法,isSorted()来检查相同生成内容的有效性,并根据每个内容进行相应排序4种不同的种类。

总之,我认为我的编辑可能节省了一部分时间/纳秒,但是我无法实现与整数测试相同的时间。希望我没有错过任何明显的内容,如果需要,欢迎编辑。干杯

答案 1 :(得分:0)

好吧,我无法判断这是否会产生任何影响,因为我机器上的计时器很糟糕,但我认为这个算法中的大部分工作都是通过交换功能完成的,所以考虑如何特别是提高效率,函数调用/返回本身可能会消耗周期,也许每次调用函数时创建临时变量也需要循环,所以如果交换工作完成,代码可能会更高效线。虽然当我在我的机器上进行测试时,并不是很明显,因为每次运行程序时纳米定位器返回的结果为+/- 20%

public class QSort2 {

static int findpivot(Comparable[] A, int i, int j) {
    return (i + j) / 2;
}

 static Comparable temp;

static void quicksort(Comparable[] A, int i, int j) { // Quicksort
    int pivotindex = findpivot(A, i, j);  // Pick a pivot
 // swap(A, pivotindex, j);               // Stick pivot at end
    temp = A[pivotindex];
    A[pivotindex] = A[j];
    A[j] = temp;
    int k = partition(A, i, j - 1, A[j]);
    //swap(A, k, j);                        // Put pivot in place
    temp = A[k];
    A[k] = A[j];
    A[j] = temp;
    if ((k - i) > 1) quicksort(A, i, k - 1);  // Sort left partition
    if ((j - k) > 1) quicksort(A, k + 1, j);  // Sort right partition
}

static int partition(Comparable[] A, int left, int right, Comparable pivot) {
    while (left <= right) { // Move bounds inward until they meet
        while (A[left].compareTo(pivot) < 0) left++;
        while ((right >= left) && (A[right].compareTo(pivot) >= 0)) right--;
        if (right > left) {
            //swap(A, left, right);} // Swap out-of-place values
            temp = A[left];
            A[left] = A[right];
            A[right] = temp;
        }
    }
    return left;            // Return first position in right partition
}

}