C++STL反復器法のadvanceとprev法の浅い分析


【概要】
反復器はSTLにおいて重要な1本であり,prevとdistanceがその基本手法である.distance法は非常に簡単で、ここでは後述しないが、主にprev法およびその関連方法であるadvance法について簡単に紹介し、使用説明を行い、文末にコード例を添付する.
【Advanceメソッド】
Advance iterator
Advances the iterator it by n element positions. If it is a random-access iterator, the function uses just once operator+ or operator-. Otherwise, the function uses repeatedly the increase or decrease operator (operator++ or operator--) until n elements have been advanced. advance反復器とは、反復器itをnビット移動することである.itがランダムアクセス反復器である場合、関数は1回の演算子計算操作を行い、そうでない場合、関数は反復器に対してn回の反復計算操作を行う.コードの例
// advance example
#include <iostream>     // std::cout
#include <iterator>     // std::advance
#include <list>         // std::list

int main () {
  std::list<int> mylist;
  for (int i=0; i<10; i++) mylist.push_back (i*10);

  std::list<int>::iterator it = mylist.begin();

  std::advance (it,5);

  std::cout << "The sixth element in mylist is: " << *it << '
';// 50 return 0; }

解析
注意:5回移動すると、5番目の要素ではなく6番目の要素が出力されます.
【Prevメソッド】
Get iterator to previous element
Returns an iterator pointing to the element that it would be pointing to if advanced  -n  positions. If it is a random-access iterator, the function uses just once  operator+  or  operator- . Otherwise, the function uses repeatedly the increase or decrease operator ( operator++  or  operator-- ) on the copied iterator until n elements have been advanced.
訳す
ランダムアクセス反復器の場合は、1回の演算子操作(+または-)のみが実行されます.そうでない場合は、n回の継続的な減算またはインクリメント操作が実行されます.
コードの例
#include <iostream>     // std::cout
#include <iterator>     // std::advance
#include <list>         // std::list
#include <algorithm>

int main () {
  std::list<int> mylist;
  for (int i=0; i<10; i++) mylist.push_back (i*10);

//std::cout<<*upper_bound(mylist.begin(), mylist.end(), 100)<<std::endl;//     
  std::cout<<*lower_bound(mylist.begin(), mylist.end(), 0)<<std::endl;//    0
  std::cout<<*prev(upper_bound(mylist.begin(), mylist.end(), 100))<<std::endl;//    90
  std::cout<<*prev(++upper_bound(mylist.begin(), mylist.end(), 90))<<std::endl;//     
//std::cout<<*prev(lower_bound(mylist.begin(), mylist.end(), 0))<<std::endl;//     
  return 0;
}

解析
prevはVC 6にある.0では実現できず、VS 2010では実現できる.実際に実現される動作は、反復器を単位長だけ減算することであり、いわゆる増幅動作やランダム反復器として使用されるか否かに応じた1回またはn回の動作は見られない.
【複盤】
詳細は、LeetCodeのSearch for a Range(検索)を参照してください.
詳細:http://blog.csdn.net/u013630349/article/details/47099915
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        const int l = distance(nums.begin(), lower_bound(nums.begin(), nums.end(), target));
        const int u = distance(nums.begin(), --upper_bound(nums.begin(), nums.end(), target));
        if (nums[l] != target) // not found
        	return vector<int> { -1, -1 };
        else
        	return vector<int> { l, u };
    }
};

解析:
ソースコードはACを検証し、「prev(...)」を「--(...)」に変更しただけです.