2012-03-22 7 views
3

タプルのリストを持っています。リストはタプルの最初の要素に基づいてソートされていますが、2番目と最後の要素はランダムな順序です。今度は、範囲内の最初の要素を持つすべてのタプルを検索します。つまり、(tuple.first>-Xtuple.first<X)のタプルをすべて返します。これらの返ってくるタプルの中で、私はタプルの2番目の要素で最大値と最小値を見つける必要があります。どのようにSTLアルゴリズムはこれを実装できますか?範囲内の最初の要素を持つすべてのタプルを見つけるSTLアルゴリズム

答えて

1

、あなたは「面白い」タプルの範囲を区切るイテレータのペアを取得するためにequal_rangeを使用することができます。

It const begin = std::lower_bound(list.begin(), list.end(), 
            [X](Tuple const& t) { 
             return t.first > -X; 
            }); 

It const end = std::upper_bound(begin, list.end(), 
           [X](Tuple const& t) { 
            return t.first < X; 
           }); 

std::pair<It,It> const range = std::make_range(begin, end); 

その後、あなたは、単にこの範囲を反復し、登録することができますあなたが見る最小値と最大値:

int min = INT_MAX, max = INT_MIN; 

for (Tuple const& t: range) { 
    if (t.second < min) { min = t.second; } 
    if (t.second > max) { max = t.second; } 
} 

// min and max are correctly set 

そう...それは、単一のSTLアルゴリズムではありません。

注:std::min_elementstd::max_elementが存在しますが、それは範囲にわたり二回ループする意味し、それはしかし確かに実現可能です。

Tuple const& min = *std::min_element(range.first, range.second, 
         [](Tuple const& left, Tuple const& right) { 
          return left.second < right.second; 
         }); 

Tuple const& max = *std::max_element(range.first, range.second, 
         [](Tuple const& left, Tuple const& right) { 
          return left.second < right.second; 
         }); 

// Or as noted by Vitali, slightly more efficient: 

auto const minmax = std::minmax_element(range.first, range.second, 
         [](Tuple const& left, Tuple const& right) { 
          return left.second < right.second; 
         }); 

Tuple const& min = *minmax.first; 
Tuple const& max = *minmax.second; 

それはタプルを与えることを注意しなく.second部材。

+0

HI Matthieu M.最初のコードは私のコンパイラ(VS2011)を渡しません。ちなみに、私は(t.first-thirdparameter> -X)&&(t.first-thirdparameter) user1285419

+0

@ user1285419:範囲が絶対値でソートされていないため、等しい範囲はカットされていないようです。代わりに 'lower_bound'と' upper_bound 'を使う必要があります。 –

+0

私は、O(2N)とは対照的に、O(max(floor(3/2(N-1))、0)を与えるminmax_elementを使用します: – Vitali

2
ListType::iterator itrFirst = std::find_if(ls.begin(), ls.end(), boost::bind(&TupleType::get<0>, _1) >= rangeStart); 
ListType::iterator itrLast = std::find_if(itrFirst, ls.end(), boost::bind(&TupleType::get<0>, _1) > rangeEnd); 
for(;itrFirst != itrLast; ++itrFirst) // Print keys for elements in range 
    std::cout << itrFirst->get<0>() << std::endl; 

私は最近のコンパイラを持っている場合、boost ::はstd ::と置き換えることができます(私はしません)。それがすでにソートされているので

+0

ありがとうございます。コードはきちんとしています:)私は自分のコードでタプルを使用するのはあまりにも複雑かもしれないことがわかりました。ですから、代わりにペアを使用するように変更します。 [code] ベクトル> ls; ベクタ ::イテレータitrFirst = std :: find_if(ls.begin()、ls.end()、boost :: bind(&pair :: first、_1)> = -0.01)。 ベクタ ::イテレータitrLast = std :: find_if(itrFirst、ls.end()、boost :: bind(&pair :: first、_1)> 0.01); [/ code] しかし、動作しません。 – user1285419

+0

コンパイラのエラーは何ですか?このコードでは、boostを動作させる必要があります。あるいは、コンパイラにpost C++ 98がある場合は、代わりにを組み込み、std :: bindを使用することができます。 – Ylisar

関連する問題