当前位置: 首页 > 知识库问答 >
问题:

如何确定INT数组上合并排序的可能运行时间?

周奇文
2023-03-14

我正在测试一些排序算法的运行时间,我在一个1280000大小的数组上测试了这个算法,得到了大约0.246秒的运行时间。我现在试图计算出我的算法在两倍大小(2560000)的数组上的理论运行时间。我试图找出如何基于合并排序的big-O计算运行时间,即nlog(n)。我在nlogn算法中插入了.246,但得到了一个负数。谷歌和其他堆栈溢出问题并没有完全起到帮助作用。我的mergeSort工作正常,但我在下面附上了它的代码。感谢您的帮助,提前感谢!

/**
 * This is another sorting algorithm where the data array is first split
 * into two, then recursively sorted, at each recursive level the method
 * will merge the current two variables together, and by the time the method
 * reaches the root call the array will be sorted.
 * @param data: The array that needs to be sorted.
 * @param first: The starting index of the sort.
 * @param n : The ending index of the sort.
 */
public static void mergeSort(int[] data, int first, int n) {

    if (data.length < 2) {
        return;
    }
    int n1;//first element of first half
    int n2;//first element of the second half
    if (n > 1) {
        //figure out the size of the array
        n1 = n / 2;
        n2 = n - n1;

        mergeSort(data, first, n1);
        mergeSort(data, first + n1, n2);

        //now merge the two halves
        merge(data, first, n1, n2);
    }

}

private static void merge(int[] data, int first, int n1, int n2) {
    int[] temp = new int[n1 + n2];
    int copied = 0;
    int copied1 = 0;
    int copied2 = 0;
    int i;

    while ((copied1 < n1) && (copied2 < n2)) {
        if (data[first + copied1] < data[first + n1 + copied2]) {
            temp[copied++] = data[first + (copied1++)];
        } else {
            temp[copied++] = data[first + n1 + (copied2++)];
        }
    }
    //make sure copied1 is completely transferred over
    while (copied1 < n1) {
        temp[copied++] = data[first + (copied1++)];
    }
    //copy temp into data to complete the process
    for (i = 0; i < copied; i++) {
        data[first + i] = temp[i];
    }

}

共有2个答案

傅增
2023-03-14

您的测试规模非常小。

您需要多次重复您的实验,并使用许多不同的大小,以便您可以绘制不同时间消耗图的图。

原因:在物理处理器上,机器使用缓存:快速内存,因此处理器得到最佳使用。程序完全加载到缓存中需要一段时间。

这意味着,第一次运行程序时,需要花费更多的时间,因为加载程序时浪费了部分时间。这叫做冷启动。第二次,可以从上一次运行之前执行的工作中受益。这叫做热启动。

此外,运行时间往往也取决于外部因素。假设你运行了这个程序,但同时网络上发生了一些事情,或者你插入了一个USB设备。在这种情况下,操作系统将暂停执行,并首先对事件进行一些簿记。簿记可以运行到毫秒,因此对单次运行有重大影响。

此外,您需要尝试不同的阵列。排序的数组通常比未排序的数组排序更快。这是因为许多合并实现使用交换(以提高性能),从而执行较少的交换。

震荡:你应该使用不同的数组,不同的大小,并经常重复这个实验,以平衡缓存等方面。

如果您这样做了,您可以如下确定运行时间。由于时间复杂度为O(n logn),这意味着函数采用以下形式:

a*n log n+b*n+c*log n+d

您可以将此公式插入最小二乘方法的Vandermonde矩阵中:

[  1    log(n_1)    n_1    n_1*log(n_1)  ]                 [ t_1 ]
[  1    log(n_2)    n_2    n_1*log(n_2)  ]      [ d ]      [ t_2 ]
[  1    log(n_3)    n_3    n_1*log(n_3)  ]      [ c ]      [ t_3 ]
[  1    log(n_4)    n_4    n_1*log(n_4)  ]   x  [ b ]  =   [ t_4 ]
[  1    log(n_5)    n_5    n_1*log(n_5)  ]      [ a ]      [ t_5 ]
[  1      ...       ...        ...       ]                 [ ... ]
[  1    log(n_m)    n_m    n_1*log(n_m)  ]                 [ t_m ]

或者用矩阵表示法:

X * w = t

使用n_i实验的数组大小it_i排序此数组所需的时间。

然后,您可以通过计算以下各项来确定常数:

w = (X^T*X)^-1*X*t

例如,您可以使用GNU/Octave执行此操作。

然后,您可以使用最小二乘法导出abcd。这应该给出一个很好的时间近似值。

如果它们差异太大,则说明您的实现有问题。如果a为(接近)零,则您的算法可能表现为sub O(n log n),并且如果函数跟不上数据点,则行为更强(因此O(n^2))

卢子民
2023-03-14

在“理论”中,合并排序是一种复杂度为O(n.log(n))的算法<这是我们都知道的事实,但事实上,许多因素对我们不利,对我们有利。i、 e.内存限制、CPU过载以及Java堆。

=

0.246=alpha*n*log(n)
其中n=1,280,000,alpha是我们的机器过程因子

0.246=alpha*1.28E 6*log(1.28E6)--

现在让我们用计算出的alpha替换数字,n=2560000:

估计值=3.14689524e-8*2.56E6*log(2.56E6)--

所以大约需要0.516秒。

注意:这仅在您拥有无限资源且没有后台进程时有效。

 类似资料:
  • 对于这个项目,我得到了一个字符串数组和一个整数数组。int[1]是字符串[1]的排名。我需要使用mergesort按1到n的顺序对int数组进行排序,我在下面已经完成了这项工作。但是当int数组被移动时,我还需要切换字符串数组的位置,以便它们都被排序,如果这有意义的话?我不知道我的编码有什么问题,甚至我的想法是否真的有效,但我一直在stringSorted[k]=stringRight[j]上得到

  • 问题是== 将nums1和nums2合并到一个按非递减顺序排序的数组中。 最终排序的数组不应由函数返回,而应存储在数组 nums1 中。为了适应这种情况,nums1 的长度为 m n,其中前 m 个元素表示应合并的元素,最后 n 个元素设置为 0 并应忽略。nums2 的长度为 n。 我的代码中有什么错误??? 您的意见 我的产出 预期产出

  • 我有三个排序数组,如下所示 这些数组根据数组中每个对象的名称属性进行排序。下面是我从Java转换为合并两个排序数组的方法 这里是两个数组的工作小提琴http://jsfiddle.net/euRn5/.什么是最好的方法来实现相同的n个数组,我目前的想法是一个接一个,合并它与以前合并到最后项目,像n=i的东西。这是最好的方法吗?

  • 我有一个结构数组 我希望合并并按升序排序数组。然而,当我执行合并时,没有任何变化。这是我用来创建struct数组的代码,以及MergeSort的函数调用。最大用户数是我从二叉树中转换节点数得到的整数,它应该是数组的最大数量。 任何提示或提示都将不胜感激! 编辑:当我尝试编写一些printf语句时,我注意到这些值是负数。但是存储在结构中的值是正数。这个错误的原因是什么?

  • 事情是这样的。我在做leetcode 164最大间隙。最佳解决方案是桶排序。 这让我对排序问题有了更多的思考。假设我们有如下列表: 2、5、19、444、-14、89、16、77 我认为,我们可以用两个不同的范围来排列这些数字,(min, mid)(mid, max)和mid-应该是min(max-min)/2; 因此我们得到了(-14215)(216444) 我们将min设置为最左侧,max设置

  • 我被要求做一个按升序对数组进行排序的程序。我这样做了: 输入不会超过10个数字。这可以用比我这里更少的代码完成吗?我希望代码尽可能短。任何帮助都将不胜感激。谢谢!