为什么快速排序的经过时间在这种情况下是如此不规则,而应该严格增加?

时间:2018-03-03 04:08:07

标签: java sorting quicksort

快速排序算法的平均案例时间复杂度为O(nlogn)。这意味着它应该随着n值的增加而严格增加。 但在这种情况下,为什么时间在增加 - 减少 - 增加。 为什么它随着n

值的增加而减少

我使用java

的函数生成随机输入

这将是什么解决方案?

public class Qsort {
static Scanner sc = new Scanner(System.in);
public static void main(String args[]) throws IOException {
File file = new File("Qtest.txt");
PrintWriter output = new PrintWriter(file);
int n,i;
System.out.println("Enter the times of iteration");
n = sc.nextInt();
for(int j=1000;j<=n*1000;j=j+1000)
{
    Random r = new Random();
    int array[];
    array = new int[j];
    for(i=0;i<j;i++)
    {
        array[i] = r.nextInt(2000);
    }
    long startTime = System.nanoTime();
    Qsort(array,0,j-1);
    long endTime = System.nanoTime();
    output.println(j + " " + (endTime-startTime));
    System.out.println("After sorting the time elapsed is " +(endTime-startTime));
}
output.close();
}

快速排序的排序功能

public static void Qsort(int A[],int start,int end)
{
    if(start>=end)  return;
    int p = partition(A,start,end);
    Qsort(A,start,p-1);
    Qsort(A,p+1,end);
}
public static int partition(int A[],int start,int end)
{
    int pivot = A[end];
    int p = start;
    for(int i =start;i<end;i++)
    {
        if(A[i]<=pivot)
        {
            int temp = A[i];
            A[i] = A[p];
            A[p] = temp;
            p++;
        }
    }
    int temp = A[p];
    A[p] = A[end];
    A[end] = temp;
    return p;
}
}

我得到的输出:

输入迭代次数 10

对于1000个输入:排序后经过的时间是779133

对于2000输入:排序后经过的时间是8350639

对于3000个输入:排序后经过的时间是607856

对于4000个输入:排序后经过的时间是833593

对于5000个输入:排序后经过的时间是1042426

对于6000个输入:排序后经过的时间是1283195

对于7000个输入:排序后经过的时间是1497488

对于8000个输入:排序后经过的时间是1261182

对于9000个输入:排序后经过的时间是1207128

对于10000个输入:排序后经过的时间是1427456

1 个答案:

答案 0 :(得分:2)

您的问题中有两个问题:测量算法复杂度和微基准测试。

算法时间复杂度与操作数一起使用。您所测量的是快速排序所花费的时间 - 这使其成为微基准测试。

微观标记很难。在第一次运行时,您很可能会看到JVM预热时间。在第二次删除它可能是指令缓存或JIT编译。我建议以运行它之前的方式重新运行测试,对10000个元素进行排序!其他因素也可能影响结果,例如机器中的CPU利用率,数组中的随机性(有时交换有时不会发生) - 通常需要微基准测试多次运行每个“实验”并仅得出结论以统计的方式,使用标准误差,百分位等,而不是从单个实验中提取它。

底线:预热确实有助于消除一些特定于JVM的噪声,操作次数可以更精确地测量时间复杂度。

以下代码是您的代码版本,用于计算操作次数并进行预热:

public class QSort {
    private static int numOps = 0;
    static Scanner sc = new Scanner(System.in);

    public static void main(String args[]) throws IOException {
        File file = new File("Qtest.txt");
        PrintWriter output = new PrintWriter(file);
        int n, i;
        System.out.println("warming up...");
        Qsort(randomInts(1000000), 0, 100000-1);
        System.out.println("Enter the times of iteration");
        n = sc.nextInt();
        for (int j = 1000; j <= n * 1000; j = j + 1000) {
            int[] array = randomInts(j);
            long startTime = System.nanoTime();
            numOps = 0;
            Qsort(array, 0, j - 1);
            long endTime = System.nanoTime();
            output.println(j + " " + (endTime - startTime) + " " + numOps);
            System.out.println("After sorting the time elapsed is " + (endTime - startTime) + " numOps: " + numOps);
        }
        output.close();
    }

    private static int[] randomInts(int j) {
        int i;Random r = new Random();
        int array[];
        array = new int[j];
        for (i = 0; i < j; i++) {
            array[i] = r.nextInt(2000);
        }
        return array;
    }

    public static void Qsort(int A[], int start, int end) {
        if (start >= end) return;
        int p = partition(A, start, end);
        Qsort(A, start, p - 1);
        Qsort(A, p + 1, end);
    }

    public static int partition(int A[], int start, int end) {
        int pivot = A[end];
        int p = start;
        for (int i = start; i < end; i++) {
            if (A[i] <= pivot) {
                int temp = A[i];
                A[i] = A[p];
                A[p] = temp;
                p++;
                numOps++;
            }
        }
        int temp = A[p];
        A[p] = A[end];
        A[end] = temp;
        return p;
    }
}

输出:

warming up...
Enter the times of iteration
20
After sorting the time elapsed is 94206 numOps: 5191
After sorting the time elapsed is 150524 numOps: 12718
After sorting the time elapsed is 232478 numOps: 20359
After sorting the time elapsed is 314819 numOps: 31098
After sorting the time elapsed is 475933 numOps: 38483
After sorting the time elapsed is 500866 numOps: 55114
After sorting the time elapsed is 614642 numOps: 57251
After sorting the time elapsed is 693324 numOps: 68683
After sorting the time elapsed is 738800 numOps: 83332
After sorting the time elapsed is 798644 numOps: 83057
After sorting the time elapsed is 899891 numOps: 99975
After sorting the time elapsed is 987163 numOps: 113854
After sorting the time elapsed is 1059323 numOps: 124735
After sorting the time elapsed is 1103815 numOps: 143278
After sorting the time elapsed is 1192974 numOps: 164740
After sorting the time elapsed is 1276277 numOps: 166781
After sorting the time elapsed is 1344138 numOps: 180460
After sorting the time elapsed is 1439943 numOps: 204095
After sorting the time elapsed is 1593336 numOps: 209483
After sorting the time elapsed is 1644561 numOps: 225523