2016-03-25 11 views
0

Cで2次元配列N * Nの最大値を比較したい場合があります。私はO(N^2)アルゴリズムで単純にそれを行うことができますが、それは遅すぎると思います。最大値を見つける2次元配列N * Nの比較数が少ない

私は別の方法について考えました。私は単純に1回ループし、行と列を同時に検索し、複雑さを減らそうとします。 (私はO(2(n-1))だと思います)あなたは私が何をしようとしているのかをこの絵で見ることができます。私は列と行の内容をチェックするために、同じループを使用

Table

もっと知りたいことは何ですか?同様に、2次元配列をO(N log N)の複雑さでソートしますか?値がソートされていないと仮定します。

+0

私は、このようなアプローチがキャッシュに影響を与えるので、物事を非常に遅くすると推測しています。 –

+2

列と行を検索すると、空間的な場所が失われます。どのくらいの速さのアルゴリズムが実行されるかを決める唯一のことではないことを覚えておきましょ実際には、長さN * Nの平坦な1次元配列の最大値を得るよりも速くなることはありません。 – Matt

+1

マルチコアを使用すると、コアごとの複雑さを減らすことができます。 1コアあたりの行ごとに最大値を見つけること。最大値の最大値を求めます。 –

答えて

4

M x M要素の2次元配列が決してソートされていない場合、O(M^2)よりもうまくいくとは限りません。

行列にはM^2要素があるので、ソートするとO(M^2 log M^2)の複雑さがあります。大部分の適切な並べ替えはO(N log N)であり、N = M^2。

+0

最高の解決策は、実際の問題によって異なります。 N * N配列内のいくつかの小さな調整を行った後で繰り返し最大値を見つけなければならない場合、ソートされた配列を維持する方がはるかに優れている可能性があります。 –

3

[コア、中]のチャンクに分割します。最大化する各チャンクの並列に結果から骨を選んでください。

+0

しかし、各チャンクには依然としてループの依存関係があるため、複数の一時的な最大値を使用することによって各チャンクのループをさらに改善できます。 – user3528438

0

確かに、dbushは複雑さの点で正しい答えを持っています。

実際の実行時間(複雑さだけでなく)を「高速」にしたい場合は、キャッシュを考慮する必要があります。並行して行と列を下げることは、データの局所性が非常に悪く、データの行数が比較的多い場合は、列を反復処理するときにキャッシュミスが発生します。最大値を見つけるには、少なくとも1回はすべての要素をタッチしなければなりません。「行の大」順序でそれらをタッチするのが最も速くなります。

1

あなたはおそらく...

を1次元配列に配列をキャストし、平坦化されたポインタを反復処理することができ、私は説明します:

あなたはおそらく知っているように、メモリ内の2次元配列が格納されています平らな状態で。この例では

| c[0][0] | | c[0][1] | | c[1][0] | | c[1][1] | | c[2][0] | ... 
| Byte 1 | | Byte 2 | | Byte 3 | | Byte 4 | | Byte 5 | ... 

c[1][1] == ((char*)c)[3]:配列char c[4][2]はこのようになります。このため

dbushが指摘するように、すべてのメンバーが同じタイプであるとき、それは安全に1次元配列に2次元配列をキャストすることが可能です、すなわち

int my_array[20][20]; 

for (int i = 0; i < 400 ; i++) { 
    ((int *)(my_array))[i] = i; 
} 

// my_array[19][0] == 180; 

(アップ彼の答えを投票)、もしあなたの行列はM x Mの要素です。そして、M^2はあなたが得ようとしている最良の配列です。このように配列を平坦化すれば、操作の前にメモリをコピーする必要がなくなります。良いかもしれない1次元配列に配列をキャストする理由

EDIT

誰かが尋ねました。

考え方は、ネストされた内部ループを回避し、オプティマイザの作業を容易にすることです。コンパイラは、ループが単一のディメンションループであり、配列のサイズが固定されている場合、ループを展開する可能性が高くなります。

+0

なぜアレイを平坦化すると違いが生じるのですか? – user3528438

+0

ループを手動でアンロールしない限り、ループ自体に関連する操作を保存して2Dの内部ループを回避し、コンパイラのオプティマイザが外側ループを簡単に展開できるようにします(配列のサイズが静的)。 – Myst

+0

@Myst 20×20アレイの場合、200ではなく400までループすることを願っています – FredK

関連する問題