2016-09-02 2 views
1

多くの場合、セグメントの端がお互いに交差する範囲のセグメントがあります。これらのセグメントをポリラインにマージしたいと思います。範囲のセグメントをポリラインの範囲にマージ/結合するためのアルゴリズムが必要です

O(N_segments)に余分なストレージを使用せずに(たとえば、セグメントポイントのツリーや他の空間データ構造を構築してその上で作業する必要がない)アルゴリズムがありますか?

私が持っているセグメントの数は、O(10)です。だから、それらをハッシュテーブルやマップ(赤黒の木)のような動的なデータ構造に入れることは、そのデータ構造をスタックに置いてメモリの割り当てを避けなければ、最後のO(N^2)ループよりも高価になるでしょう(私が使用していポリラインは限りポイントの数が十分小さいとして割り当てを回避する、small_vectorを使用して実装され

現在、私はこれを作ってみた:。

polylines = [] 
// 1. Append each segment to a range of polylines, merging when possible: 
for each segment in segments: 
    for each polyline in polylines: 
     merge_result = merge(segment, polyline) 
     if (not merge_result) continue 
     polyline = merge_result 
     goto done 

    // either polylines empty or no merge possible 
    polylines.append(segment) 

    done: 
     continue 

// 2. Try to merge the polylines among themselves until no more merges are possible 
// Pure brute force, quadratic 
done = false 
while not done: 
    for p1 in polylines: 
     for p2 in polylines[p1..end]: 
      merge_result = merge(p1, p2) 
      if not merge: continue 
      p1 = merge_result 
      polylines.remove(p2) 
      done = false 
      goto restart 
    restart: continue 

しかし、第二のループはっきりと二次的なので、セグメント間でセグメントのシーケンスをマージ/結合/結合するためのより良いアルゴリズムがあるのだろうかと思います。

+1

なぜデータ構造の作成を避けるのですか?私は、複数のセグメントが約O(n)時間で終点を共有しているかどうかを検出するために、セグメントの終点のマップを作成します。 – MrSmith42

+1

[関連記事](http://stackoverflow.com/questions/1436091/joining-unordered-line-segments?rq=1)は、検索をスピードアップするためにエンドポイントのハッシュを計算することを提案しています。 –

+0

@ MrSmith42私はO(10)セグメントの注文を扱うので、スタック上にマップを作成しない限り、ダイナミックマップを作成するコストは最終的なO(N^2)ループのコストを超過するでしょう。これが私が余分なデータ構造なしでそれを行うためのより良いアルゴリズムに興味を持った理由です。スタック上のマップを試してみて、ベンチマークします。提案していただきありがとうございます。 – gnzlbg

答えて

1

O(n)メソッドが存在する可能性があることを真剣に疑う。

正確に同じ座標を持つセグメント四肢を検出するO(n log(n))メソッドです。これは、 "データ構造"を使用しますが、非常に単純なものです(ベクトルのみ)。

1)すべてのセグメントのすべての四肢の要素ベクトル(x、y、i)を作成します。四肢の座標を表し、iは四肢の指標である(例えば、セグメントの2つの端部について2 *セグメントインデックスおよび2 *セグメントインデックス+1)。

2)正確に同じ座標を持つ点がベクターに連続している、ベクタースキャン(X、Y)

3)上の辞書式順序を有するベクトルをソート(インデックスと私はあなたが盗んでき

私はこのアルゴリズムを3Dメッシュのマージに使用していますが、これは単純で非常に高速です。ハッシュマップやセットを使用する場合よりもはるかに高速です(重複する1秒間に1,000万ポイント)。

0

問題は、配列内の重複を見つけることと同じです。この問題は一般的にO(N)時間と0(1)空間では解決できません。 O(N log N)の複雑さを持たせるためにソートを使うことも、データ構造を使うこともできます。 一般の場合、重複を見つけるにはthisをご覧ください。 の特殊なの場合、サイズnの配列に範囲0、... n-1の要素が含まれている場合、O(N)時間と0(1)の空間解が存在します。インデックスとして使用することができます。this投稿を参照してください。

しかし、もしあなたがとにかく約10個の要素しか話していないのであれば、二次ループでさえ多分傷つくことはありません。時間が本当に重要な場合は、いずれの場合も両方の方法をベンチマークする必要があります。問題は、純粋な複雑さのクラスがlarge Nのためだけに重要になるので、誰もあなたのマシン上でわずか10個の要素だけ速くなることを誰にも教えてくれないということです。小さなNに対して、O(N^2)アルゴリズムはO(N log n)アルゴリズムよりもはるかに高速である。また、メモリの割り当て、キャッシュの効率性、および他に何が起きているかは別として、だから、私の提案:あなたが本当にスピードを気にしている場合はベンチマーク、そうでない場合は気にしないでください。

関連する問題