繁体   English   中英

向量中的 C++ push_back

[英]C++ push_back in vectors

我构建了一个递归 function,它读取一个向量作为输入并返回一个新向量,其中每两个连续的元素被切换。 例如输入: 1 2 3 4 5 6和 output: 2 1 4 3 6 5 我不明白的是,当我这样写 function 时:

vector<int> reverse(vector<int> v) {

    if (v.size() < 2)
        return v;
    else
    {
        int pos1 = v.at(0);  //= 1
        int pos2 = v.at(1);  //= 2

        v.erase(v.begin());  //v = 2 3 4 5 6
        v.erase(v.begin());  //v = 3 4 5 6

        vector<int> rev = reverse(v);

        rev.push_back(pos2);  //rev = 2
        rev.push_back(pos1);  //rev = 2 1

        return rev;
    }
}

我得到6 5 4 3 2 1 我知道vector::push_back()在向量的末尾添加元素,那么为什么不2 1 4 3 6 5呢? 当我以这种方式编写它时,它给了我一个很好的答案( 2 1 4 3 6 5 ),但我知道为什么:

vector<int> reverse(vector<int> v) {

    if (v.size() < 2)
        return v;
    else
    {
        int pos1 = v.at(v.size() - 2);  //= 5
        int pos2 = v.at(v.size() - 1);  //= 6

        v.pop_back();  //v = 1 2 3 4 5
        v.pop_back();  //v = 1 2 3 4

        vector<int> rev = reverse(v);  //call the recursive function

        rev.push_back(pos2);  //rev = 5
        rev.push_back(pos1);  //rev = 6 5

        return rev;
    }
}

main() function 是这样的:

int main() {

    vector<int> w;
    int zahl;

    cout << "Please give the vector or any letter to end the input: "<< endl;

    while (cin >> zahl)
    {
        w.push_back(zahl);
    }

    for (int elem : reverse(w))
    {
        cout << elem << ", ";
    }
    return 0;
}

这是一个简单的修复。

您的代码的问题是递归步骤没有正确地将正确构造的子结果转换为稍大的子结果。 你会想做:

// Correctly create the head of the result.
vector<int> rev = {pos2, pos1};

// Now you want to handle the tail, and assuming the output of reverse
// is correct for smaller lists, this would be achieved by appending
// the rest.
const auto sub = reverse(v);
rev.insert(rev.end(), sub.begin(), sub.end());

这可以确保如果您的列表以1 2开头,它将变成带有2 1的列表,然后是正确处理的尾部。

您的第二个代码有效,因为您正在反向处理序列,因此您的递归步骤实际上是正确的。

您获得的结果不正确,因为在对 function 的最后一次调用中,您返回一个空向量,然后在该向量的后面推动最后一对数字倒置,因此6,5 ,因此您在调用中继续进行堆。 让我们看一下您在每次通话(第一次通话,第二次通话,ecc.)时的情况:

  1. v= [1,2,3,4,5,6] -> 递归调用
  2. v= [3,4,5,6] -> 递归调用
  3. v= [5,6] -> 递归调用
  4. v= [] -> 返回空向量
  5. rev= [] ,将 v 的前两个元素以相反的顺序推回,所以 rev= [6,5] ->return rev
  6. rev= [6,5] ,将 v 的前两个元素倒序推回,所以 rev= [6,5,4,3] ->return rev
  7. rev= [6,5,4,3] ,将 v 的前两个元素以相反的顺序推回,所以 rev= [6,5,4,3,2,1]

出于这个原因,您首先需要有一个前两个数字颠倒的向量,然后按照上面的建议附加处理后的尾部。

请注意,每次调用 function 时,您都在构建向量的副本。 您可以创建反向副本,而无需修改作为参数给出的参数的副本。 我会改用迭代器,这样每次你的 function “看到”原始向量的一小部分,而不触及它。 这里有一个实现:

vector<int> reverse(vector<int>::const_iterator begin, vector<int>::const_iterator end) {

    if (begin==end-1) //the vector has an odd number of elements, let's append the last element
        return vector<int>(1, *(end-1));
    else if(begin>=end) //the vector has en even number of elements
        return vector<int>();
    else
    {
        vector<int> pairWiseReversed({*(begin+1), *begin});
        vector<int> tail=reverse(begin+2, end);
        pairWiseReversed.insert(pairWiseReversed.end(), tail.begin(), tail.end());
        return pairWiseReversed;
    }
}

vector<int> buildReversed(const vector<int>& input){
    return reverse(input.begin(), input.end());
}

这里有一个主要的:

int main() {
    vector<int> v{1,2,3,4,5,6};
    cout<<"Input vector"<<endl;
    for(auto n:v)
        cout<<n<<" ";
    cout<<endl;

    vector<int> res=buildReversed(v);
    cout<<"Output vector"<<endl;
    for(auto n:res)
        cout<<n<<" ";
    cout<<endl;
    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM