Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.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

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++ 检查向量是否使用divide et impera算法排序_C++_Algorithm_Recursion_Vector_Divide And Conquer - Fatal编程技术网

C++ 检查向量是否使用divide et impera算法排序

C++ 检查向量是否使用divide et impera算法排序,c++,algorithm,recursion,vector,divide-and-conquer,C++,Algorithm,Recursion,Vector,Divide And Conquer,我试图检查向量是否使用分治算法排序,以下是我迄今为止编写的代码: #include <iostream> #include <vector> using namespace std; bool isOrdered(std::vector <int> v, int left, int right) { int mid = (left + right)/2; if (left == right){ if (left == 0) ret

我试图检查向量是否使用分治算法排序,以下是我迄今为止编写的代码:

#include <iostream>
#include <vector>

using namespace std;

bool isOrdered(std::vector <int> v, int left, int right)
{
int mid = (left + right)/2;

if (left == right){
    if (left == 0)
        return true;
    else
        return v[left-1] <= v[left];
}
else if (left + 1 == right)
{
    if (v[left] <= v[right])
        return true;
    else
        return false;
}
else if (left > right)
{
    if (v[left] > v[right])
        return true;
    else
        return false;
}
else
{
    return isOrdered(v, left, mid) && isOrdered(v, mid+1, right);
}
}

int main()
{
std::vector <int> v = {2, 2, 3, 2, 2};
cout << isOrdered(v, 0, v.size() - 1);
return 0;
}
它在某些情况下似乎不起作用,在调试过程中,我不断添加特定的基本情况,使其适用于一个输入,但这不会使其适用于另一个输入,我一直这样做,直到我意识到我有一个算法错误。我基本上是这样想的:把向量分成子向量,如果所有子向量都是有序的,那么整个向量都是有序的。然而,这种方法很快就会失败。如果输入长度不是2的幂,那么它最终会将其分解为长度为1的某些子向量,这些子向量总是按顺序排列的。例如,如果输入是2 2 3 2怎么办?子向量是{2,2}、{3}和{2,2},它们都是有序的,但整个向量不是


那么我应该如何看待这个问题呢?我试图通过添加返回v[left-1]来使它对长度为1的子向量有效,为什么还要使用这个困难的算法?为了检查向量是否排序,每个成员v[i]不能大于下一个v[i+1]


分治算法更有用,例如,在已排序的向量中查找某些内容,但在检查向量是否已排序时,简单的线性算法由于可读性更好。

为什么还要使用这种困难的算法?为了检查向量是否排序,每个成员v[i]不能大于下一个v[i+1]

#include <iostream>
#include <vector>

using namespace std;

bool isOrdered(const vector <int> &v, int left, int right) {
    int mid = (left + right)/2;
    if (left == right)
        return true;
    else
        return v[mid]<=v[mid+1] && isOrdered(v, left, mid) && isOrdered(v, mid+1, right);
}

int main()
{
    vector <int> v = {2, 2, 3, 2, 2};
    cout << isOrdered(v, 0, v.size() - 1);
    return 0;
}

分治算法更有用,例如,在已排序的向量中查找某些内容,但在检查向量是否已排序时,简单的线性算法由于可读性更好。

从递归开始:

#include <iostream>
#include <vector>

using namespace std;

bool isOrdered(const vector <int> &v, int left, int right) {
    int mid = (left + right)/2;
    if (left == right)
        return true;
    else
        return v[mid]<=v[mid+1] && isOrdered(v, left, mid) && isOrdered(v, mid+1, right);
}

int main()
{
    vector <int> v = {2, 2, 3, 2, 2};
    cout << isOrdered(v, 0, v.size() - 1);
    return 0;
}

如果两个子范围都已订购,并且如果低范围的最后一项低于高范围的第一项,则订购范围:

return isOrdered(v, left, mid - 1) && isOrdered(v, mid, right) && v[mid - 1] <= v[mid];
保持停止条件:当范围为空时,不能从参数发生或只有一个元素。 这些是有序范围

所以我们得到:

bool isOrdered(const std::vector<int>& v, std::size_t left, std::size_t right)
{
    if (left == right) { // Only one element
        return true;
    } else {
        const auto mid = (left + right + 1) / 2;
        return v[mid - 1] <= v[mid]
            && isOrdered(v, left, mid - 1)
            && isOrdered(v, mid, right);
    }
}

从递归开始:


如果两个子范围都已订购,并且如果低范围的最后一项低于高范围的第一项,则订购范围:

return isOrdered(v, left, mid - 1) && isOrdered(v, mid, right) && v[mid - 1] <= v[mid];
保持停止条件:当范围为空时,不能从参数发生或只有一个元素。 这些是有序范围

所以我们得到:

bool isOrdered(const std::vector<int>& v, std::size_t left, std::size_t right)
{
    if (left == right) { // Only one element
        return true;
    } else {
        const auto mid = (left + right + 1) / 2;
        return v[mid - 1] <= v[mid]
            && isOrdered(v, left, mid - 1)
            && isOrdered(v, mid, right);
    }
}


一旦有2个组,您就需要停止,以便所有组都重叠。那就是{2,2,3,2,2}应该递归到组{2,2},{2,3},{3,2},{2,2}。顺便说一句,通过常量引用而不是复制来传递向量。@NathanOliver,我也想到了这一点。。不确定它是否算作“分而治之”,但不管怎样,我都应该如何递归地进行呢?@Lastrevio2只要在right-left==1时停止递归即可。此外,左+右/2有可能溢出。若要解决此问题,请参见:@NathanOliver:仅当我们使用有符号索引时才存在潜在问题;-若要在有符号/无符号索引之间提供war ^ ^您需要在拥有2个组后停止,以便所有组都重叠。那就是{2,2,3,2,2}应该递归到组{2,2},{2,3},{3,2},{2,2}。顺便说一句,通过常量引用而不是复制来传递向量。@NathanOliver,我也想到了这一点。。不确定它是否算作“分而治之”,但不管怎样,我都应该如何递归地进行呢?@Lastrevio2只要在right-left==1时停止递归即可。此外,左+右/2有可能溢出。若要解决此问题,请参见:@NathanOliver:仅当我们使用有符号索引时才存在潜在问题;-要在有符号/无符号索引之间引发战争,这不是答案。这是一个家庭作业。。。当然,我不是在实际项目中使用它,但我试着学习“分而治之”,一般来说,如果不付诸实践,我还能学到什么呢?@Lastrevio2:作为家庭作业练习或学习体验,没关系。我的意思是不要在现实生活中使用它,例如在工作中,在编程工作中。这不是答案。这是一个家庭作业练习。。。当然,我不是在实际项目中使用它,但我试着学习“分而治之”,一般来说,如果不付诸实践,我还能学到什么呢?@Lastrevio2:作为家庭作业练习或学习体验,没关系。我的意思是不要在现实生活中使用它,例如在工作中,在编程工作中。虽然这段代码可以解决这个问题,但如果解释一下它是如何解决的/为什么解决的,答案会更好。请记住,您的答案不仅针对提出问题的用户,也针对找到问题的所有其他人。还要注意int mid=left+right/2;不安全,因为它可能溢出。这是从@jarod42派生的实现。您仍然应该记录它的工作方式/原因。评论是临时的,可以随时删除。你的答案应该站在自己的脚上,而不是重复
虽然这段代码可以解决这个问题,但如果解释一下它是如何解决的,或者为什么解决这个问题,答案会更好。请记住,您的答案不仅针对提出问题的用户,也针对找到问题的所有其他人。还要注意int mid=left+right/2;不安全,因为它可能溢出。这是从@jarod42派生的实现。您仍然应该记录它的工作方式/原因。评论是临时的,可以随时删除。你的答案应该站在自己的脚上,不依赖任何外部信息。如果两个子范围都已订购,并且如果低范围的最后一项低于高范围,则范围已订购:啊,我明白了!如果两者都是有序的,那么最高的元素是最后一个,最低的元素是第一个,所以如果低范围的最后一项低于高范围的第一项,那么整个东西都是有序的。现在开始有意义了。另外,我发现有趣的是您编写了std::size\t。我知道它是C++独有的,但不在C中,但我不知道你必须写STD::对于它,我使用C:B来避免你写STD:有时候,即使你没有用名字空间STD说‘``;就像我可以在代码块上说string而不是std::string,而不使用名称空间std,所以我不知道size\t是否也是这样,所以我假设在更普通的编译器/编辑器中,您必须将std::放在size\t前面才能工作?或者使用名称空间std@Lastrevio2由于C++具有命名空间C++,所以在STD命名空间内放置了sisit。要实现100%的可移植性,您需要std::size\u t或至少使用std::size\u t;。通常情况下,您可以不使用它,因为C定义也被拉入,但是为什么要尝试命运呢?@Lastrevio2:size\t和其他一些类型/typedef也可以来自没有名称空间std的C-header。尽管std::string不是其中之一。在某些情况下,ADL也允许省略函数调用的std::for。如果两个子范围都已排序,并且如果低范围的最后一项低于高范围,则范围已排序:啊,我明白了!如果两者都是有序的,那么最高的元素是最后一个,最低的元素是第一个,所以如果低范围的最后一项低于高范围的第一项,那么整个东西都是有序的。现在开始有意义了。另外,我发现有趣的是您编写了std::size\t。我知道它是C++独有的,但不在C中,但我不知道你必须写STD::对于它,我使用C:B来避免你写STD:有时候,即使你没有用名字空间STD说‘``;就像我可以在代码块上说string而不是std::string,而不使用名称空间std,所以我不知道size\t是否也是这样,所以我假设在更普通的编译器/编辑器中,您必须将std::放在size\t前面才能工作?或者使用名称空间std@Lastrevio2由于C++具有命名空间C++,所以在STD命名空间内放置了sisit。要实现100%的可移植性,您需要std::size\u t或至少使用std::size\u t;。通常情况下,您可以不使用它,因为C定义也被拉入,但是为什么要尝试命运呢?@Lastrevio2:size\t和其他一些类型/typedef也可以来自没有名称空间std的C-header。尽管std::string不是其中之一。在某些情况下,ADL也允许省略函数调用的std::for。