简体   繁体   English

向量中的 C++ push_back

[英]C++ push_back in vectors

I built a recursive function that reads a vector as input and returns a new vector in which every two consecutive elements are switched.我构建了一个递归 function,它读取一个向量作为输入并返回一个新向量,其中每两个连续的元素被切换。 For example input: 1 2 3 4 5 6 and output: 2 1 4 3 6 5 .例如输入: 1 2 3 4 5 6和 output: 2 1 4 3 6 5 The thing I don't get is that when I write the function this way:我不明白的是,当我这样写 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;
    }
}

i get 6 5 4 3 2 1 .我得到6 5 4 3 2 1 I know the vector::push_back() adds the elements at the end of the vector, so why not 2 1 4 3 6 5 ?我知道vector::push_back()在向量的末尾添加元素,那么为什么不2 1 4 3 6 5呢? When I wrote it this way it gave me the good answer though ( 2 1 4 3 6 5 ) but idk why:当我以这种方式编写它时,它给了我一个很好的答案( 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;
    }
}

The main() function is this: 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;
}

It's an easy fix.这是一个简单的修复。

The problem with your code is that the recursive step does not correctly translate a correctly constructed sub-result to a slightly larger one.您的代码的问题是递归步骤没有正确地将正确构造的子结果转换为稍大的子结果。 You would want to do:你会想做:

// 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());

This ensures that if your list starts with 1 2 , it would turn into a list with 2 1 , followed by a correctly processed tail.这可以确保如果您的列表以1 2开头,它将变成带有2 1的列表,然后是正确处理的尾部。

Your second code worked because you were processing the sequence in reverse, so your recursive step was in fact correct.您的第二个代码有效,因为您正在反向处理序列,因此您的递归步骤实际上是正确的。

The result you obtain is incorrect because in the last call to your function you return an empty vector, and then you push at the back of this vector your last pair of numbers inverted, so 6,5 , so you do proceding back in the call stack.您获得的结果不正确,因为在对 function 的最后一次调用中,您返回一个空向量,然后在该向量的后面推动最后一对数字倒置,因此6,5 ,因此您在调用中继续进行堆。 Let's have a look to what you have at every call (first call, second call, ecc.):让我们看一下您在每次通话(第一次通话,第二次通话,ecc.)时的情况:

  1. v= [1,2,3,4,5,6] ->recursive call v= [1,2,3,4,5,6] -> 递归调用
  2. v= [3,4,5,6] ->recursive call v= [3,4,5,6] -> 递归调用
  3. v= [5,6] ->recursive call v= [5,6] -> 递归调用
  4. v= [] ->return empty vector v= [] -> 返回空向量
  5. rev= [] , push back the first two elements of v in reverse order, so rev= [6,5] ->return rev rev= [] ,将 v 的前两个元素以相反的顺序推回,所以 rev= [6,5] ->return rev
  6. rev= [6,5] , push back the first two elements of v in reverse order, so rev= [6,5,4,3] ->return rev rev= [6,5] ,将 v 的前两个元素倒序推回,所以 rev= [6,5,4,3] ->return rev
  7. rev= [6,5,4,3] , push back the first two elements of v in reverse order, so rev= [6,5,4,3,2,1] rev= [6,5,4,3] ,将 v 的前两个元素以相反的顺序推回,所以 rev= [6,5,4,3,2,1]

For this reason, you need first to have a vector with the first two numbers reversed and then attach the processed tail, as suggested above.出于这个原因,您首先需要有一个前两个数字颠倒的向量,然后按照上面的建议附加处理后的尾部。

Please note that you are constructing copies of the vector every time you call the function.请注意,每次调用 function 时,您都在构建向量的副本。 You can create a reversed copy without modifying the copy of the argument given as argument.您可以创建反向副本,而无需修改作为参数给出的参数的副本。 I would use iterators instead, so that every time your function "sees" a smaller portion of the original vector, without touching it.我会改用迭代器,这样每次你的 function “看到”原始向量的一小部分,而不触及它。 Here an implementation:这里有一个实现:

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());
}

And here a main:这里有一个主要的:

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