为什么我的合并排序不像O(n*lgn))
Why is my merge sort not behaving like a O (n * lg n))?
我基于Cormen‘s Book上的伪代码实现了这种合并排序。我正在复制它,因为它很短:
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];
}
该部分应为O(n)
另一个应该是O(n*lg n),其中lg是2个基本上的日志
void mergeSort(vector<double> &array, int start, int end) {
if (start < end) {
int mid = (end - start) / 2 + start;
mergeSort(array, start, mid);
mergeSort(array, mid + 1, end);
merge(array, start, mid, end);
}
}
我用大小为1000(10^3)、10000(10^4)、50000(5*10^4),100000(10^5)、250000(2.5*10^5),500000(5*10^2)的随机向量实例做了一些实验。每个大小有30个实例。这是我对每个实例大小的平均结果:
1000 - ~0.000 s
10000 - 0.344 s
50000 - 20.456 s
100000 - 59.083 s
250000 - 360.814 s
500000 - 1729.245 s
运行合并排序时,我从linux时间命令中获取的所有经过时间(占用用户时间)。可见,它不是O(n*lgn)行为。我在这里缺少什么?我不知道它是否相关,但我的系统配置是:
OS: Fedora 18 - 64 bits
Processor: Intel® Core™ i3 CPU M 380 @ 2.53GHz × 4
Memory: 2.8 Gi
B
罪魁祸首是:
vector<double> 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)算法
向量的重新定位似乎花费了很多时间。添加到矢量不是O(1)运算。尝试将向量更改为基本的C类型数组,您会注意到差异。此外,我从这些值中看到,它绝不是指数型的。也许是一个更高的多项式。
相关文章:
- 我的神经网络不起作用 [XOR 问题]
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 我的字符计数代码计算错误.为什么
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- cmake在我的项目中所需的所有静态库都不成功
- 为什么我的代码在输出中增加了93天
- 我的简单if-else语句是如何无法访问的代码
- 为什么我的for循环不能正确获取argv
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- 0-1背包代码中的错误.我的代码中有什么错误
- 当我的阵列太大时出现分段错误
- 如何确认我的constexpr表达式实际上已经在编译时执行
- 为什么二进制搜索在我的测试中不起作用
- 如何指定我希望我的LIB链接到的DLL文件?-Visual Studio 2019
- 我的代码中有错误吗?使用BGI图形的C++代码对我不起作用
- 当我在main中声明了我的2d数组时,为什么我的程序会退出
- OpenGL在启用深度测试时不会丢弃我的碎片
- 为什么我的 std::ref 无法按预期工作?
- clang整洁10忽略了我的NOLINT命令
- 为什么我的合并排序不像O(n*lgn))