我试图实现一个非常简单的合并排序版本(不考虑为此目的进行的所有优化),我的目标是返回合并数组的新副本,而不是通过引用传递输入数组并将合并元素复制到其中的传统方法。
为此,我的代码如下:
vector<int> merge(vector<int> left, vector<int> right)
{
vector<int> result;
int leftIdx = 0;
int rightIdx = 0;
int resultIdx = 0;
while (leftIdx < left.size() && rightIdx < right.size()) {
if (left[leftIdx] < right[rightIdx]) {
result[resultIdx++] = left[leftIdx++];
} else {
result[resultIdx++] = right[rightIdx++];
}
}
while (leftIdx < left.size()) {
result[resultIdx++] = left[leftIdx++];
}
while (rightIdx < right.size()) {
result[resultIdx++] = right[rightIdx++];
}
return result;
}
vector<int> MergeSort(vector<int> intArr)
{
vector<int> recresult;
// base - if array is of length 1, nothing to do, return it as is
if (intArr.size() == 1) {
return intArr;
} else {
int mid = intArr.size() / 2;
// copy left half
vector<int> leftArr(intArr.begin(), intArr.begin() + mid);
// copy right half
vector<int> rightArr(intArr.begin() + mid, intArr.end());
MergeSort(leftArr);
MergeSort(rightArr);
recresult = merge(leftArr, rightArr);
}
return recresult;
}
>
我知道来自合并的这个数组是一个本地数组,因此我将它返回给mergesort,而mergesort又将它返回给main。假设这不会从后续的递归调用中传入和传出,我是否错了?
我对这段代码的测试输入是{1,0,9}。我应该得到{0,1,9},但我得到32767。
我错过了什么?
首先对于merge
——应该将常量引用传递给参数,否则会产生太多不必要的副本。此外,当您在empty中创建并按索引访问时,还可以访问结果
。使用int
作为索引不是一个好主意。所以简化的版本可能是:
vector<int> merge(const vector<int> &left, const vector<int> &right)
{
vector<int> result;
auto lit = left.begin();
auto rit = right.begin();
while( lit != left.end() || rit != right.end() ) {
bool lft = false;
if( rit == right.end() )
lft = true;
else {
if( lit != left.end() )
lft = *lit < *rit;
}
result.push_back( lft ? *lit++ : *rit++ );
}
return result;
}
或更接近您的版本:
vector<int> merge(const vector<int> &left, const vector<int> &right)
{
vector<int> result( left.size() + right.size() );
auto rst = result.begin();
auto lit = left.begin();
auto rit = right.begin();
while( lit != left.end() && rit != right.end() )
*rst++ = *lit < *rit ? *lit++ : *rit++;
std::copy( lit, left.end(), rst );
std::copy( rit, right.end(), rst );
return result;
}
对MergeSort
的递归调用不起任何作用,因为intArr
是按值(复制)获取的,而您没有使用结果值。
像这样的方法应该有用:
auto newLeft = MergeSort(leftArr);
auto newRight = MergeSort(rightArr);
recresult = merge(newLeft, newRight);
正如Slava在评论中提到的,在访问结果
时也有UB,因为它的大小
为0:
vector<int> result; // size = 0
// ...
result[resultIdx++] = left[leftIdx++]; // UB!
在使用操作符[]
访问元素之前,应该调用std::vector::resize
。
我想写一个时间O(n*lgk)的算法,将k个排序数组合并成一个排序数组,其中n是所有输入数组的元素总数。 你能告诉我怎么做吗? 编辑:我编写了以下算法: 你能告诉我这是否正确吗?
我写了3个方法来实现递归合并排序,参数数量有限(没有aux、lo、mid、hi)。我认为我的工作是这样的,但它并没有返回一个排序数组,尽管它在运行时没有任何编译错误。我已经摆弄了4个小时,似乎无法弄清楚我做错了什么,没有合并一个有序数组。我只从我的助教那里得到了非常模糊的输入,并且能够修复我正在遇到的一些问题,但是该方法仍然没有对项数组进行排序。欢迎任何关于我在这里做错了什么的建议。谢谢!
我想用Javascript实现合并排序作为一种学习经验。我有mergeSort(unsortedArray)函数,它接受一个未经排序的数组,并使用合并排序策略对其进行排序。mergeSort()调用merge(leftArray,rightArray),后者将两个数组合并在一起,得到一个数组。 我认为问题出在merge()函数上。在数组[8,8,7,5,4,6,3,2,1,5,9,8,7,6,5,
问题内容: 这是在采访中问我的,这是我提供的解决方案: 有没有更有效的方法可以做到这一点? 编辑:更正的长度方法。 问题答案: 稍有改进,但是在主循环之后,当到达另一个输入数组的末尾时,可以用来复制其中一个输入数组的结尾。但是,那不会改变你解决方案的性能特征。
问题内容: 给定两个排序数组,如下所示: 我希望输出为: 要么: 我知道我可以执行以下操作: 我只是想知道是否有一种更快的方法,因为我要处理的数组具有数百万个元素。 任何想法都欢迎。谢谢 问题答案: 由于您使用numpy,因此我怀疑bisec根本不会对您有所帮助。因此,我建议您做两件事: 千万 不能 使用,使用方法,而不是这种种取代阵列,避免了复制。 必须使用没有到位的。因此,不要手动使用逻辑。I
问题是关于从16:43到23:34的视频中的合并排序http://youtu.be/M814OagXWTI?t=16m43s 在退出左/右排序合并递归后,我不清楚我们是如何合并回这些子数组的。让我们从最底部开始,当我们的元素被分成两个子数组时,一个左子数组称为B,一个右子数组称为C。在16:43左右,我们跳转到合并函数,对数组B和C进行排序,这两个数组只有8和3。合并排序函数(下面的代码)基本上通