Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么我的合并排序不像O(n*lgn))?_C++_Performance_Algorithm_Sorting - Fatal编程技术网

C++ 为什么我的合并排序不像O(n*lgn))?

C++ 为什么我的合并排序不像O(n*lgn))?,c++,performance,algorithm,sorting,C++,Performance,Algorithm,Sorting,我基于上可用的伪代码实现这种合并排序。我正在复制它,因为它很短: void merge(vector<double> &array, int start, int mid, int end) { int i = start; int j = mid + 1; int k = start; vector<double> b(array.size()); while (i <= mid && j <

我基于上可用的伪代码实现这种合并排序。我正在复制它,因为它很短:

void merge(vector<double> &array, int start, int mid, int end) {
    int i = start;
    int j = mid + 1;
    int k = start;
    vector<double> b(array.size());

    while (i <= mid && j <= end) {
        if (array[i] <= array[j])
            b[k++] = array[i++];
        else
            b[k++] = array[j++];
    }

    while(i <= mid)
        b[k++] = array[i++];

    while(j <= end)
        b[k++] = array[j++];

    for (k = start; k <= end; k++)
        array[k] = b[k];
}
运行合并排序时,我从linux time命令(take users time)获取的所有已用时间。 可见,这不是一个O(n*lgn)行为。我错过了什么? 我不知道这是否相关,但我的系统配置是:

OS: Fedora 18 - 64 bits
Processor: Intel® Core™ i3 CPU M 380 @ 2.53GHz × 4
Memory: 2.8 Gi
B

这似乎占用了很多时间。向向量添加不是O(1)操作。尝试将向量更改为基本的C类型数组,您会注意到其中的差异。而且,从数值上看,它不是指数型的。可能是更高的多项式。

罪魁祸首是:

vector<double> b(array.size());
向量b(array.size()); 假设您从50万个条目的向量开始。对
mergeSort
的初始调用将对50万个条目的向量调用
mergeSort
,但只对前250000个元素进行排序。(然后它将在下半部分重复。)对
mergeSort
的下一次调用将接收完整的500000个元素数组,并调用
mergeSort
对数组的第一个和第二个125000个元素进行排序。等等每次在此过程中,
mergeSort
都会收到50万个条目的向量,但只对子集进行排序。最终,您将调用
merge
,其中每次调用都将分配并初始化一个包含50万个元素的临时数组

结果是n2*log(n)行为。这不是指数行为,但仍然不好

我看到三种不同的解决方案:

  • 将该临时
    b
    分配一次,并将其作为参数传递给
    mergeSort
    merge
  • merge
    中分配一个大小为
    end-start+1
    的临时数组。现在,您必须使用偏移量来处理
    b[0]
    对应于
    array[start]
    的事实
  • 合并到位。在这里你不需要临时工。但是,这是非常重要的,它将使算法成为O(N*(log(N))^2)算法
您运行的是调试代码还是优化代码?差异可能很大,因为您的一些循环可以并行化。从理论上讲,就比较而言,
merge
算法是
O(n)
:但你做的远不止这些。你做了大量的访问、递增、赋值,甚至还分配了一个新的向量。所有这些都会影响性能(更具体地说,缓存不好的内存和冷内存会影响性能)用于
矢量b(结束-开始),并使用
k=0
。你的
b
比它应该的要大得多,不确定这是问题所在。这可能是你的问题,
向量
填充构造具有线性时间。只需指出就地合并是非常重要的(尽管可能),并且会使算法变慢。
OS: Fedora 18 - 64 bits
Processor: Intel® Core™ i3 CPU M 380 @ 2.53GHz × 4
Memory: 2.8 Gi
vector<double> b(array.size());