Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.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+有效地将排序与向量合并+; 我使用向量作为函数实现C++中的合并排序 参数而不是索引(开始、结束)。不过,我很乐意 知道这样做在速度方面是否有任何折衷 空间复杂性_C++_Sorting_Merge - Fatal编程技术网

如何使用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
数组,用于合并在算法的任何步骤中生成的两个排序
向量中的任何一个。显然,您的解决方案使用的内存更多。在第一次合并时,它会分配两个v
n/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
看起来很不错!