Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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++_Algorithm_C++11_Recursion_Mergesort - Fatal编程技术网

C++ 为什么向量迭代器指向边界之外?

C++ 为什么向量迭代器指向边界之外?,c++,algorithm,c++11,recursion,mergesort,C++,Algorithm,C++11,Recursion,Mergesort,我正在研究一个递归的mergesort算法,一个迭代器出界了。我敢肯定,我的问题的根源是我的算法有缺陷,但我已经花了好几天的时间来研究它,我只是没有看到我的失误。我不知道该往哪个方向走。能找个比我更有经验/更聪明的人看看吗?(Github上提供了带驱动程序的完整程序。) 输出为: before: 50 5 40 10 30 15 20 20 10 25 after : -1808873259 5 10 10 15 20 20 25 30 40 50 /* ^ * E

我正在研究一个递归的mergesort算法,一个迭代器出界了。我敢肯定,我的问题的根源是我的算法有缺陷,但我已经花了好几天的时间来研究它,我只是没有看到我的失误。我不知道该往哪个方向走。能找个比我更有经验/更聪明的人看看吗?(Github上提供了带驱动程序的完整程序。)

输出为:

before: 50 5 40 10 30 15 20 20 10 25 
after : -1808873259 5 10 10 15 20 20 25 30 40 50 
/*      ^  
 *      Extra recursive call, and out-of-bounds.
 */
要清楚的是,我必须返回类型为T的向量,在这个例子中是int,但是我知道使用void函数更好

template <typename T>
vector<T> mergesort(typename vector<T>::iterator begin, typename vector<T>::iterator end){
    vector<T> newVector;
    if (begin!=end){
        vector<T> tmp1;
        vector<T> tmp2;
        typename vector<T>::iterator mid1 = begin;
        typename vector<T>::iterator mid2 = begin;

        long origDistance = distance(begin,end);
        long endOfRange1 = origDistance/2;
        long begOfRange2 = endOfRange1+1;

        advance(mid1,endOfRange1);
        advance(mid2,begOfRange2);

        tmp1 = mergesort<T>(begin,mid1);
        tmp2 = mergesort<T>(mid2,end);

        //"merge()" is from the STL, link in comments. 
        merge(tmp1.begin(),tmp1.end(),tmp2.begin(),tmp2.end(), back_inserter(newVector));

    } else {
        newVector.push_back(*begin);
    }
    return newVector;
}
模板
向量合并排序(typename向量::迭代器开始,typename向量::迭代器结束){
向量newVector;
如果(开始!=结束){
载体tmp1;
载体tmp2;
typename向量::迭代器mid1=开始;
typename向量::迭代器mid2=开始;
长距离=距离(开始、结束);
长内法兰1=起始距离/2;
长起始范围2=内折1+1;
提前(中期1,中期1);
前进(中段2,起始段2);
tmp1=合并排序(开始,中间1);
tmp2=合并排序(中间2,结束);
//“merge()”来自STL,注释中的链接。
合并(tmp1.begin(),tmp1.end(),tmp2.begin(),tmp2.end(),back_inserter(newVector));
}否则{
newVector.push_back(*开始);
}
返回newVector;
}

begin==end
时,取消引用
begin
。这是未定义的行为。可能您希望
如果(origDistance==1)
则将单个元素推回并返回。

您在
开始==end
时解除对
开始的引用。这是未定义的行为。可能您希望
如果(origDistance==1)
则将单个元素推回并返回。

这里我将向您演示如何执行此操作

template <typename T>
void mergesort(typename vector<T>::iterator, typename vector<T>::iterator);

// ...

    mergesort<int>(vec.begin(), vec.end());
    newVector = vec;

// ...

template <typename T>
void mergesort(typename vector<T>::iterator begin, typename vector<T>::iterator end){
    auto const N = std::distance(begin, end);
    if (N <= 1) return;                   
    auto const middle = std::next(begin, N / 2);
    mergesort<T>(begin, middle);
    mergesort<T>(middle, end);
    std::inplace_merge(begin, middle, end); 
}

STL已经就位了,为什么要重新实现它呢?使用这种方法,你不必费心思考,因为它有着难以逾越的界限。

在这里,我将向你展示如何做到这一点

template <typename T>
void mergesort(typename vector<T>::iterator, typename vector<T>::iterator);

// ...

    mergesort<int>(vec.begin(), vec.end());
    newVector = vec;

// ...

template <typename T>
void mergesort(typename vector<T>::iterator begin, typename vector<T>::iterator end){
    auto const N = std::distance(begin, end);
    if (N <= 1) return;                   
    auto const middle = std::next(begin, N / 2);
    mergesort<T>(begin, middle);
    mergesort<T>(middle, end);
    std::inplace_merge(begin, middle, end); 
}

STL已经就位了,为什么要重新实现它呢?使用这种方法,您不必考虑边界问题。

如果
end
指向向量的最后一个元素,您的函数看起来可以工作。但是,在示例程序中,您可以这样称呼它:

newVector=mergesort(vec.begin(),vec.end());
vec.end()。因此,您的函数会出错,因为它最终会尝试访问您传入的第二个迭代器所指向的元素

您可以像这样调用函数:
mergesort(vec.begin(),vec.end()-1)


但是,这会让阅读您的代码的其他人感到惊讶。重写你的代码>合并代码> >代码>函数,遵循正常的C++范围约定,也就是说,参数<代码>结束>代码>应该结束。code>mid1
应等于
mid2

如果
end
指向向量的最后一个元素,则函数看起来可以工作。但是,在示例程序中,您可以这样称呼它:

newVector=mergesort(vec.begin(),vec.end());
vec.end()。因此,您的函数会出错,因为它最终会尝试访问您传入的第二个迭代器所指向的元素

您可以像这样调用函数:
mergesort(vec.begin(),vec.end()-1)


但是,这会让阅读您的代码的其他人感到惊讶。重写你的代码>合并代码> >代码>函数,遵循正常的C++范围约定,也就是说,参数<代码>结束>代码>应该结束。code>mid1
应该等于
mid2

好的-如果不弄清楚这一点,就无法入睡,这是我获得正确方向的巨大功劳-以下是获得正确输出的代码:

before: 50 5 40 10 30 15 20 20 10 25 
after : 5 10 10 15 20 20 25 30 40 50 
template <typename T>
vector<T> mergesort(typename vector<T>::iterator begin, typename vector<T>::iterator end){
    vector<T> newVector;
    long origDistance = distance(begin,end); /*Get distance first.*/

    if (origDistance==1){ /*Added better anchor case checking for distance.*/
        newVector.push_back(*begin);
        return newVector;
    }

    vector<T> tmp1;
    vector<T> tmp2;
    typename vector<T>::iterator mid1 = begin;
    typename vector<T>::iterator mid2 = begin;

    long endOfRange1 = origDistance/2;
    long begOfRange2 = endOfRange1;/*Edited from: endOfRange+1*/

    advance(mid1,endOfRange1);
    advance(mid2,begOfRange2);

    tmp1 = mergesort<T>(begin,mid1);
    tmp2 = mergesort<T>(mid2,end);

    merge(tmp1.begin(),tmp1.end(),tmp2.begin(),tmp2.end(), back_inserter(newVector));
        return newVector;
}
模板
向量合并排序(typename向量::迭代器开始,typename向量::迭代器结束){
向量newVector;
long origDistance=距离(开始、结束);/*首先获取距离*/
如果(origDistance==1){/*添加了更好的锚案例检查距离*/
newVector.push_back(*开始);
返回newVector;
}
载体tmp1;
载体tmp2;
typename向量::迭代器mid1=开始;
typename向量::迭代器mid2=开始;
长内法兰1=起始距离/2;
long begOfRange2=endOfRange1;/*编辑自:endOfRange+1*/
提前(中期1,中期1);
前进(中段2,起始段2);
tmp1=合并排序(开始,中间1);
tmp2=合并排序(中间2,结束);
合并(tmp1.begin(),tmp1.end(),tmp2.begin(),tmp2.end(),back_inserter(newVector));
返回newVector;
}

好的-如果不弄清楚这一点,我就无法入睡,这是让我走上正确方向的巨大功劳-以下是获得正确输出的代码:

before: 50 5 40 10 30 15 20 20 10 25 
after : 5 10 10 15 20 20 25 30 40 50 
template <typename T>
vector<T> mergesort(typename vector<T>::iterator begin, typename vector<T>::iterator end){
    vector<T> newVector;
    long origDistance = distance(begin,end); /*Get distance first.*/

    if (origDistance==1){ /*Added better anchor case checking for distance.*/
        newVector.push_back(*begin);
        return newVector;
    }

    vector<T> tmp1;
    vector<T> tmp2;
    typename vector<T>::iterator mid1 = begin;
    typename vector<T>::iterator mid2 = begin;

    long endOfRange1 = origDistance/2;
    long begOfRange2 = endOfRange1;/*Edited from: endOfRange+1*/

    advance(mid1,endOfRange1);
    advance(mid2,begOfRange2);

    tmp1 = mergesort<T>(begin,mid1);
    tmp2 = mergesort<T>(mid2,end);

    merge(tmp1.begin(),tmp1.end(),tmp2.begin(),tmp2.end(), back_inserter(newVector));
        return newVector;
}
模板
向量合并排序(typename向量::迭代器开始,typename向量::迭代器结束){
向量newVector;
long origDistance=距离(开始、结束);/*首先获取距离*/
如果(origDistance==1){/*添加了更好的锚案例检查距离*/
newVector.push_back(*开始);
返回newVector;
}
载体tmp1;
载体tmp2;
typename向量::迭代器mid1=开始;
typename向量::迭代器mid2=开始;
长内法兰1=起始距离/2;
long begOfRange2=endOfRange1;/*编辑自:endOfRange+1*/
提前(中期1,中期1);
前进(中段2,起始段2);
tmp1=合并排序(开始,中间1);
tmp2=合并排序(中间2,结束);
合并(tmp1.begin(),tmp1.end(),tmp2.begin(),tmp2.end(),back_inserter(newVector));
返回newVector;
}

例如,将很快更新输出。您是否知道
某个向量.end()
不是最后一个元素,而是最后一个元素之后的元素?取消对它的引用是违法的。我不知道这是什么意思