欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[C/C++标准库]_[初级]_[删除反转枚举reverse_iterator详解]

程序员文章站 2022-07-15 09:40:14
...

场景

  1. std::vector里有rbegin()rend()反转枚举迭代器,我们可以通过这个反转枚举std::vector<T>::reverse_iterator进行倒序迭代,问题是当使用反转枚举时如果有需要删除的元素怎么办?vector.erase()方法的参数只能是索引枚举std::vector<T>::iterator,不能是反转枚举。

说明

  1. 索引枚举和反转枚举是存在下标对应关系

    • 如图1. 反转枚举整体向右平移一个元素,它左边第一元素就是.rend(). 通过reverse_iterator.base()对应的iterator是图1所示的垂直对应的。

      图1:
      [C/C++标准库]_[初级]_[删除反转枚举reverse_iterator详解]

    • 反转枚举转换为索引枚举通过调用rite.base()获得索引枚举;而创建反转枚举需要索引枚举作为参数vector<int>::reverse_iterator(ite)

  2. 索引枚举和反转枚举对应的元素转换关系:

    *rite == *(rite.base()-1)
    或者
    *ite = *(reverse_iterator(ite)-1)
    
    即都是
    *f = *(f1-1)
    

目的

删除一个反转枚举i(从左到右位置),我们需要得到下一个反转枚举位置是i-1

  1. 先要转换为索引枚举i-1删除:

    删除索引枚举i-1,得到新的索引枚举位置代替了删除的即i-1

    auto cite = v.erase(rite.base()-1);
    
  2. 把位置i-1的顺序枚举转换为反转枚举,它的位置i-1即我们需要得到的下一个反转枚举位置。

    rite1 = VII(cite);
    

例子

//
//  main.cpp
//  TestVectorErase
//
//  Created by sai on 10/19/20.
//  Copyright (c) 2020 qixingshi. All rights reserved.
//

#include <iostream>
#include <vector>

using namespace std;

void TestVectorEraseReverseIterator()
{
    // 1. 按照索引顺序枚举
    cout << "index order" << endl;
    vector<int> v = {1,2,3,4,5,6,7,8,9,10};
    for (auto ite = v.begin(); ite != v.end(); ite++) {
        cout << *ite << " ";
    }
    cout << endl;
    
    // 2. 按照索引反转枚举
    cout << "reverse order" << endl;
    for (auto ite = v.rbegin(); ite != v.rend(); ite++) {
        cout << *ite << " ";
    }
    cout << endl;
    
    // 3. 索引顺序偏移量3的枚举值
    auto ite = v.begin()+3;
    auto offset = ite - v.begin();
    cout << "offset: " << offset << " ite: " << *ite << endl;
    
    //    3.1 该索引顺序的枚举对应的反转枚举偏移量和值.
    //    3.2 反转枚举的偏移量 = v.size()-索引顺序偏移量.
    typedef vector<int>::reverse_iterator VII;
    VII rite(ite);
    auto qite = rite -1;
    auto roffset = rite - v.rbegin();
    cout << "roffset: " << roffset << " rite: " << *rite << endl;
    cout << "*(rite-1) == *ite : " << boolalpha <<  (*qite == *ite) << endl;
    auto ite1 = rite.base();
    cout << *ite1 << endl;
    
    //    3.3 通过使用反转枚举的方法.base()获取对应的索引枚举,但是这个枚举和反转枚举值不一样。
    //        需要通过.base()-1获得等值(即相同元素)的枚举。
    auto ite2 = rite.base()-1;
    cout << *ite2 << endl;
    
    // 4. 删除反转枚举B,通过转换为对应的索引枚举值A1,调用.erase(A1)之后得到的下一个枚举A2,再通过A2
    //    创建反转枚举B1, 这个B1就是B的下一个反转枚举。
    cout << "========" << endl;
    for (auto rite1 = v.rbegin(); rite1 != v.rend(); ) {
        if (*rite1 == 3) {
            auto cite = v.erase(rite.base()-1);
            rite1 = VII(cite);
            cout << *rite1 << endl;
        }else{
            rite1++;
        }
    }
    
    
    for (auto rite1 = v.rbegin(); rite1 != v.rend(); rite1++) {
        cout << *rite1 << " ";
    }
    cout << endl;
}

int main(int argc, const char * argv[])
{
    // insert code here...
    std::cout << "Hello, World!\n";
    TestVectorEraseReverseIterator();
    getchar();
    return 0;
}

输出

Hello, World!
index order
1 2 3 4 5 6 7 8 9 10
reverse order
10 9 8 7 6 5 4 3 2 1
offset: 3 ite: 4
roffset: 7 rite: 3
*(rite-1) == *ite : true
4
3
========
2
10 9 8 7 6 5 4 2 1

参考

移除反转枚举reverse_iterator

reverse_iterator.base()

reverse_iterator