【发布时间】:2014-04-19 04:22:22
【问题描述】:
我根据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^5)。每个大小有 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 time 命令(占用用户时间)中获取的所有经过时间。 可见,这不是 O(n*lg n) 行为。我在这里缺少什么? 我不知道这是否相关,但我的系统配置是:
OS: Fedora 18 - 64 bits
Processor: Intel® Core™ i3 CPU M 380 @ 2.53GHz × 4
Memory: 2.8 Gi
B
【问题讨论】:
-
您运行的是调试代码还是优化代码?差异可能很大,因为您的某些循环可以并行化。从理论上讲,算法
merge在比较方面是O(n):但你做的远不止这些。你做了大量的访问、递增、赋值,甚至分配了一个新的向量。所有这些都会影响性能(更具体地说,缓存不佳的内存和冷内存会损害性能)。 -
尝试将
vector<double> b(array.size());更改为vector<double> b(end-start);,并使用k=0。你的b比它应该的大得多,不确定这是问题所在。 -
这可能是你的问题,
vector填充构造具有线性时间。
标签: c++ performance algorithm sorting