簡體   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