std :: out_of_range:Mergesort算法中的向量异常

时间:2018-11-29 18:51:41

标签: c++

我正在尝试在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

1 个答案:

答案 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名称空间的情况下才会引起问题(明智的程序员应避免这样做)。