【发布时间】:2018-10-03 19:35:28
【问题描述】:
我需要实现一种有效的算法来从多个排序数组中查找排序联合。因为我的程序做了很多这类操作,所以我用 C++ 模拟了它。我的第一种方法(方法 1)是简单地创建一个空向量并将其他向量中的每个元素附加到空向量,然后使用 std::sort 和 std::unique 来获得所有元素的所需排序联合。但是,我认为将所有向量元素转储到一个集合(方法 2)中可能会更有效,因为集合已经使它们变得独一无二并一次性排序。令我惊讶的是,方法 1 比方法 2 快 5 倍!我在这里做错了吗?方法2不应该更快,因为它的计算量更少吗?提前致谢
//// 带有向量的方法1:
std::vector<long> arr1{5,12,32,33,34,50};
std::vector<long> arr2{1,2,3,4,5};
std::vector<long> arr3{1,8,9,11};
std::vector<long> arr;
int main(int argc, const char * argv[]) {
double sec;
clock_t t;
t=clock();
for(long j=0; j<1000000; j++){ // repeating for benchmark
arr.clear();
for(long i=0; i<arr1.size(); i++){
arr.push_back(arr1[i]);
}
for(long i=0; i<arr2.size(); i++){
arr.push_back(arr2[i]);
}
for(long i=0; i<arr3.size(); i++){
arr.push_back(arr3[i]);
}
std::sort(arr.begin(), arr.end());
auto last = std::unique(arr.begin(), arr.end());
arr.erase(last, arr.end());
}
t=clock() - t;
sec = (double)t/CLOCKS_PER_SEC;
std::cout<<"seconds = "<< sec <<" clicks = " << t << std::endl;
return 0;
}
//// 带集合的方法2:
std::vector<long> arr1{5,12,32,33,34,50};
std::vector<long> arr2{1,2,3,4,5};
std::vector<long> arr3{1,8,9,11};
std::set<long> arr;
int main(int argc, const char * argv[]) {
double sec;
clock_t t;
t=clock();
for(long j=0; j<1000000; j++){ //repeating for benchmark
arr.clear();
arr.insert(arr1.begin(), arr1.end());
arr.insert(arr2.begin(), arr2.end());
arr.insert(arr3.begin(), arr3.end());
}
t=clock() - t;
sec = (double)t/CLOCKS_PER_SEC;
std::cout<<"seconds = "<< sec <<" clicks = " << t << std::endl;
return 0;
}
【问题讨论】:
-
如果数组已排序,为什么不合并它们并在合并时立即跳过相同的值,而不是事后过滤掉它们?
-
我们可以合并它们并保持联合排序吗?我没有想到这一点。你能详细说明一下吗?谢谢
-
在每个数组中使用一个读取索引;总是先取三个元素中最小的一个;跳过任何重复...
-
额外的数据结构会增加一些开销。我猜想 std::sort 能够利用数组已经部分排序的事实。相反,按顺序插入集合可能会导致不平衡的树,需要经常重新平衡。
标签: c++ algorithm performance