std::超出范围:合并排序算法中的向量异常 我尝试在C++中实现合并算法。您可以在下面看到我的实现。运行该算法时,出现以下错误: libc++abi.dylib:以std::out_of_range:vector类型的未捕获异常终止 中止陷阱:6 虽然这是我第一次在C++中工作,但我认为这个错误意味着我通过了一个超出某些向量范围的索引。这是正确的吗
如果这是正确的,我无法找出我在哪里超过了某个向量的边界。但是,我在控制台上打印了一些值,并注意到程序无法打印右向量中的元素。也许这暗示了索引超出范围的位置 合并排序实施std::超出范围:合并排序算法中的向量异常 我尝试在C++中实现合并算法。您可以在下面看到我的实现。运行该算法时,出现以下错误: libc++abi.dylib:以std::out_of_range:vector类型的未捕获异常终止 中止陷阱:6 虽然这是我第一次在C++中工作,但我认为这个错误意味着我通过了一个超出某些向量范围的索引。这是正确的吗,c++,C++,如果这是正确的,我无法找出我在哪里超过了某个向量的边界。但是,我在控制台上打印了一些值,并注意到程序无法打印右向量中的元素。也许这暗示了索引超出范围的位置 合并排序实施 #include <iostream> #include <vector> void merge(std::vector<int> left, std::vector<int> right, std::vector<int> array) { int leng
#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;
}
您的代码有一些地方出错,但是这个循环给出了错误
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
}
你所说的程序不会对向量排序,C++通过值传递参数,这意味着每次调用某个函数时,它将创建具有相同数据的<强>新< /强>变量。 您的
mergesort
函数应该接收向量并更改其上的值,这里您有两个选项,或者更改函数以返回新向量,或者使用和通过引用将向量传递给此函数,而不是在函数内创建具有相同值的新向量,将变量的内存引用发送到函数,这样函数就可以访问相同的变量。
您的功能应更改为
void merge(std::vector<int> &left, std::vector<int> &right, std::vector<int> &array)
{ ... }
std::vector<int> mergesort(std::vector<int> &array)
{ ... }
void合并(std::vector和left,std::vector和right,std::vector和array)
{ ... }
std::vector合并排序(std::vector&array)
{ ... }
有些时候,通过引用传递其他函数会很有用,但你会及时得到,但通常在性能方面,这是一个很好的做法,因为你不会为每个函数创建新的变量
如果不清楚,或者你想得到更好的解释,就问吧
提示
小心地命名变量,不应该使用保留名称,<代码>数组是C++保留的名称,你应该换个名字。
它实际上不是一个保留字,只有当程序员使用
使用名称空间std
时才会发生冲突,如@user4581301所述
保留是一个加载的术语。在C++中,保留的意思是无论如何都不能使用这个。数组不是保留的。如果包含了数组作为标识符,并且std名称空间由于使用名称空间std而短路(明智的程序员避免了这一点),那么使用数组作为标识符只会导致问题
您的代码有一些地方出错,但是这个循环给出了错误
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
}
你所说的程序不会对向量排序,C++通过值传递参数,这意味着每次调用某个函数时,它将创建具有相同数据的<强>新< /强>变量。
您的
mergesort
函数应该接收向量并更改其上的值,这里您有两个选项,或者更改函数以返回新向量,或者使用和通过引用将向量传递给此函数,而不是在函数内创建具有相同值的新向量,将变量的内存引用发送到函数,这样函数就可以访问相同的变量。
您的功能应更改为
void merge(std::vector<int> &left, std::vector<int> &right, std::vector<int> &array)
{ ... }
std::vector<int> mergesort(std::vector<int> &array)
{ ... }
void合并(std::vector和left,std::vector和right,std::vector和array)
{ ... }
std::vector合并排序(std::vector&array)
{ ... }
有些时候,通过引用传递其他函数会很有用,但你会及时得到,但通常在性能方面,这是一个很好的做法,因为你不会为每个函数创建新的变量
如果不清楚,或者你想得到更好的解释,就问吧
提示
小心地命名变量,不应该使用保留名称,<代码>数组是C++保留的名称,你应该换个名字。
它实际上不是一个保留字,只有当程序员使用
使用名称空间std
时才会发生冲突,如@user4581301所述
保留是一个加载的术语。在C++中,保留的意思是无论如何都不能使用这个。数组不是保留的。如果包含了数组作为标识符,并且std名称空间由于使用名称空间std而短路(明智的程序员避免了这一点),那么使用数组作为标识符只会导致问题
你为什么不调试你的程序?它将显示错误发生的位置。您应该真正基于迭代器进行合并排序。您所做的所有这些复制都将扼杀您的性能。请注意,您可能需要阅读有关引用的内容,因为默认情况下,所有类型的行为都是“值类型”,因此会复制参数。这与Java或C#相反。您的合并
函数实际上没有任何用处-您正在修改对象的副本,这些副本在函数结束时被丢弃。目前,您正在尝试在左侧传递mid+1
值,在右侧传递length-mid-1
值。但是向量的维数不是这样的。你为什么不调试你的程序呢?它将显示错误发生的位置。您应该真正基于迭代器进行合并排序。您所做的所有这些复制都将扼杀您的性能。请注意,您可能需要阅读有关引用的内容,因为默认情况下,所有类型的行为都是“值类型”,因此会复制参数。这与Java或C#相反。您的合并
函数实际上没有任何用处-您正在修改对象的副本,这些副本在函数结束时被丢弃。目前,您正在尝试在左侧传递mid+1
值,在右侧传递length-mid-1
值。但是向量的尺寸不是这样的。对提示的一个快速更正是:保留是一个加载的