如何使用C+有效地将排序与向量合并+; 我使用向量作为函数实现C++中的合并排序 参数而不是索引(开始、结束)。不过,我很乐意 知道这样做在速度方面是否有任何折衷 空间复杂性
守则:如何使用C+有效地将排序与向量合并+; 我使用向量作为函数实现C++中的合并排序 参数而不是索引(开始、结束)。不过,我很乐意 知道这样做在速度方面是否有任何折衷 空间复杂性,c++,sorting,merge,C++,Sorting,Merge,守则: void mergeSort(std::vector<int> &array) { if(array.size() == 1) return; else { const unsigned int len = array.size(); const int lo = floor((double)len/2); const int hi = ceil((double)len/2); std::vector&
void mergeSort(std::vector<int> &array) {
if(array.size() == 1) return;
else {
const unsigned int len = array.size();
const int lo = floor((double)len/2);
const int hi = ceil((double)len/2);
std::vector<int> L(&array[0], &array[lo]);
std::vector<int> R(&array[lo], &array[len]);
mergeSort(L);
mergeSort(R);
merge(array, L, R);
}
return;
}
void合并排序(标准::向量和数组){
if(array.size()==1)返回;
否则{
常量unsigned int len=array.size();
const int lo=楼层((双)长/2);
常数int hi=ceil((双)len/2);
std::向量L(&数组[0],&数组[lo]);
std::向量R(&数组[lo],&数组[len]);
合并排序(L);
合并排序(R);
合并(数组,L,R);
}
返回;
}
创建新列表每次调用merge sort可能都不是一个好办法,
但合并排序函数就是这样工作的。此外,速度有多快/多慢:
std::vector<int> L(&array[0], &array[lo]);
std::向量L(&array[0],&array[lo]);
合并函数如下所示:
void merge(
std::vector<int> &array,
std::vector<int> &L,
std::vector<int> &R
) {
std::vector<int>::iterator a = array.begin();
std::vector<int>::iterator l = L.begin();
std::vector<int>::iterator r = R.begin();
while(l != L.end() && r != R.end()) {
if (*l <= *r) {
*a = *l;
l++;
}
else {
*a = *r;
r++;
}
a++;
}
while (l != L.end()) {
*a = *l;
a++;
l++;
}
while (r != R.end()) {
*a = *r;
a++;
r++;
}
return;
无效合并(
std::向量和数组,
标准::向量&L,
向量&R
) {
std::vector::iterator a=array.begin();
std::vector::迭代器l=l.begin();
std::vector::迭代器r=r.begin();
而(l!=l.end()&&r!=r.end()){
如果(*lWell,则不需要在每次调用merge时创建新空间。
std::vector L(&array[0],&array[lo]);
将实际创建空间容纳lo
元素,并将执行lo
复制
您永远不会使用超过O(n)
的额外空间来存储值。那么,为什么不分配一个足够大的缓冲区来容纳
预先创建整个向量的副本,并使每个递归调用对数据的特定部分进行操作?这样,您就不必在每次调用时创建新的向量
另外,我还鼓励您让mergesort
只在迭代器上工作,而不是只在vector
上工作
template < typename Iterator, typename Compare>
void mergesort(Iterator s, Iterator e, Compare cmp);
template
void mergesort(迭代器s、迭代器e、比较cmp);
您可以找到我不久前实现的mergesort的一个版本。我想这应该足够了。进行合并排序所需的唯一额外内存是大小n
数组,用于合并在算法的任何步骤中生成的两个排序向量中的任何一个。显然,您的解决方案使用的内存更多。在第一次合并时,它会分配两个vn/2
长度的向量,那么它将是n/4
的四个向量,等等,总共给出n*log(n)
。这比n
稍微多一些
分配向量
的成本通常与其长度成线性关系(如果复制向量
的元素可以在O(1)中完成),但您应该记住,如果不使用自定义分配器,在堆上分配内存是一项昂贵的操作。分配内存可能会发出系统调用,这可能会使用复杂的算法来查找连续的内存块以满足您的需求。它甚至可能需要将已分配的内存块移动到其他地方。因此如果你能坚持一次分配,那么多次分配内存是没有意义的。使用std::vector
而不是迭代器的折衷方法就是你的算法不再是泛型的。由于算法本身在内部使用迭代器,我很难找到优势。你真的必须这样做测试和测量自己是否知道任何性能优势。考虑到这个问题不太可能产生明显的性能差异,但是做<代码> Lo= LeN/2;Hi=Le- lo;< /C> >避免浮点数学。;由于您使用了一体式方法,我认为使用原始数据会更快(l.data())如果你在某个循环中使用这个函数,那么如果考虑FASTISIS性能是主要目标,那么如果是这样,那么对于自上而下合并排序,对工作向量进行一次分配,并使用相互递归来根据Lev改变合并的方向。递归的el。实现自底向上的合并排序会稍微快一点。如果输入参数是指向向量或数组的开始和结束的指针,则更为通用。让暂存向量适应不可复制分配的类型并不是一件容易的事。链接实现不需要考虑到这一点。move assignable
是否不足以适应这种情况?感谢您指出,我以前从未考虑过这个问题。我没有仔细阅读代码,但我确实看到您没有移动元素。标准容器现在对其类型的要求非常宽松如果要保留,您可能想查看这些模板。太好了!谢谢@Davide。最好开始使用这些模板。而且,std::distance
看起来很不错!