我正在尝试在C ++中实现Mergesort算法。您可以在下面看到我的实现。当我运行算法时,出现以下错误:
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: vector
Abort trap: 6
虽然这是我第一次使用C ++,但我认为此错误意味着我传入的索引超出了某些向量的范围。这是正确的吗?
如果这是正确的,我无法弄清楚我超出了某些向量的范围。但是,我在控制台上打印了一些值,并注意到该程序无法正确打印矢量中的元素。也许这暗示了索引超出范围的地方。
合并排序实现
#include <iostream>
#include <vector>
void merge(std::vector<int> left, std::vector<int> right, std::vector<int> array)
{
int lengthLeft = left.size();
int lengthRight = right.size();
int i = 0; // index of smallest unpicked element in left
int j = 0; // index of smallest unpicked element in right
int k = 0; // position to be filled in array
while (i < lengthLeft && j < lengthRight)
{
if (left.at(i) <= right.at(j))
{
array.at(k) = left.at(i);
k++;
i++;
}
else
{
array.at(k) = right.at(j);
k++;
j++;
}
}
while (i < lengthLeft)
{
array.at(k) = left.at(i);
k++;
i++;
}
while (j < lengthRight)
{
array.at(k) = right.at(j);
k++;
j++;
}
}
std::vector<int> mergesort(std::vector<int> array)
{
int length = array.size();
std::cout << "Array Size: " << length << '\n';
if (length < 2)
{
return array;
}
int mid = length / 2;
std::cout << "mid = " << mid << '\n';
// Temporary vectors.
std::vector<int> left(mid);
std::vector<int> right(length - mid);
std::cout << "Left size: " << left.size() << '\n';
std::cout << "Right size: " << right.size() << '\n';
// Moving elements into temporary vectors.
for (int i = 0; i <= mid; i++)
{
left.at(i) = array.at(i);
std::cout << "Left at i: " << left.at(i) << '\n';
}
for (int i = mid + 1; i < length; i++)
{
right.at(i) = array.at(i);
std::cout << "Right at i: " << right.at(i) << '\n'; // <-- THIS DOES NOT PRINT
}
mergesort(left);
mergesort(right);
merge(left, right, array);
return array;
}
int main()
{
std::vector<int> vect = {5, 4, 3, 2, 1};
for (int i : vect)
{
std::cout << i << " " << '\n';
}
mergesort(vect);
for (int i : vect)
{
std::cout << i << '\n';
}
return 0;
}
控制台输出
5
4
3
2
1
Array Size: 5
mid = 2
Left size: 2
Right size: 3
Left at i: 5
Left at i: 4
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: vector
Abort trap: 6
答案 0 :(得分:4)
您的代码有些错误,但是此循环正在给出错误
for (int i = 0; i <= mid; i++)
{
left.at(i) = array.at(i);
std::cout << "Left at i: " << left.at(i) << '\n';
}
for (int i = mid + 1; i < length; i++)
{
right.at(i) = array.at(i);
std::cout << "Right at i: " << right.at(i) << '\n'; // <-- THIS DOES NOT PRINT
}
要解决您的错误,您必须将第一个更改为for (int i = 0; i < mid; i++)
,仅用<=
替换<
,这样它就得到前两位数字。
第二秒钟,您应该将for (int i = 0; i < length - mid; i++)
更改为right.at(i) = array.at(i);
,并将right.at(i) = array.at(mid + i);
更改为mid
,这将确保您获得剩余的3,这里的问题是您是从2
开始的它是right
,向量3
的大小仅为for (int i = 0; i < mid; i++)
{
left.at(i) = array.at(i);
std::cout << "Left at i: " << left.at(i) << '\n';
}
for (int i = 0; i < length - mid; i++)
{
right.at(i) = array.at(mid + i);
std::cout << "Right at i: " << right.at(i) << '\n'; // <-- THIS DOES NOT PRINT
}
,因为向量的索引为0,所以您从上一个索引开始,而下一次迭代超出了它的范围。
所以孔部分应该是这样
mergesort
话虽这么说,您的程序仍然无法对向量进行排序,C ++会按值传递参数,这意味着每次您使用特定输入调用函数时,它都会使用 new 变量创建一个相同的数据。
您的&
函数应该接收一个向量并更改其值,这里有两个选择,或者可以更改函数以返回新向量,或者使用{{1 }},而不是在函数内部创建具有相同值的新向量,而是将变量的内存引用发送给函数,以使函数可以访问相同的变量。
您的功能应更改为
void merge(std::vector<int> &left, std::vector<int> &right, std::vector<int> &array)
{ ... }
std::vector<int> mergesort(std::vector<int> &array)
{ ... }
有时候通过引用传递会很有用,您会及时得到,但是通常从性能角度来看,这是一个好习惯,因为您没有在每个函数中创建新变量。
如果不清楚,或者您想要更好的解释,请问。
小心地命名变量,不应使用保留的名称,array
是C ++ 保留的的名称,而应使用其他名称。
实际上这不是保留字,只有在程序员使用using namespace std
时才发生冲突,如@ user4581301所述
保留是已加载的术语。在C ++中,Reserved表示无论如何都不能使用它。数组未保留。如果将数组用作标识符,则只有在包含数组且使用命名空间std缩短了std名称空间的情况下才会引起问题(明智的程序员应避免这样做)。