2011-10-20 4 views
2

私はstd::uniqueを使用して、大きなイプシロンを持つequalsメソッドを使用してfloatベクトルのマージクラスターを取得しています。問題は、それが1のようにランを取ることであり、私はそれがどのように使用してこれを行うことができます。3.std :: unique merge

(1) ...    .  .... ..... 
(2) .     .  .  . 
(3) .    .  .  . 

にそれらを回し、「等しい」の点で平均を使用してのようにそれらをマージするものの2
にそれらを回しますC++の標準ライブラリですか?

+0

データの形式は何ですか。単に 'std :: vector 'にすることはできません。そうしないと、位置が失われます。私があなたを誤解しない限り。 –

+0

@MooingDuck:値は位置です。最初のものは1,2,3,20,25,26,27,28,35,36,37,38,39のようなものです。 – Dani

+0

「実行中」は常に連続していますか? –

答えて

2

いいえ、あなたが望むことができる標準的なアルゴリズムはありません。しかし、それは信じられないほど複雑ではありません。私はイテレーターについての仮定を最小限に抑えようとしたので、これはすべてのフォワード入力イテレーターで機能するはずです。

#include <iostream> 

template<class initer, class outiter, class predicate> 
outiter average_runs(initer begin, initer end, outiter out, predicate pred) { 
    //quit if no range 
    if (begin == end) 
     return out; 
    initer endrun = begin; 
    do { 
     //find end of run 
     while(endrun+1 != end && pred(*endrun,*(endrun+1))) 
      ++endrun; 
     //move "begin" to the middle 
     std::advance(begin, std::distance(begin,endrun)/2); 
     //output the result 
     *out++ = *begin; 
     //start next run 
     begin = ++endrun; 
    } while(endrun != end); 
    return out; 
} 

bool intclose(int l, int r) 
{ return r-l <= 1;} 
int main() { 
    int array[13] = {1,2,3,20,25,26,27,28,35,36,37,38,39}; 
    int output[13] = {}; 
    int* end = average_runs((int*)array, array+13, (int*)output, &intclose); 
    for(int* c = output; c<end; ++c) 
     std::cout << *c << ' '; 
    return 0; 
} 
//displays: 2 20 26 37 
+0

'(endrun-begin)'という表現は、フォワードイテレータでは保証されていません。 – aschepler

+0

うわー、修正されました。 'std :: distance()' ftw! –

+0

また、 'fwditer a = b;という保証が見つからない。 b ++; a ++」、「a」と「b」は同じ「場所」を指す。これは、istreamイテレータがこのアルゴリズムや類似のアルゴリズムで惨めに失敗することを意味します。 –

関連する問題