web-dev-qa-db-ja.com

配列の要素へのアクセスに一定の時間がかかるのはなぜですか?

私が配列を持っているとしましょう:

int a [] = {4,5,7,10,2,3,6}

a [3]などの要素にアクセスすると、実際にはその背後で何が起こりますか?多くのアルゴリズムの本(Cormenの本など)が一定の時間がかかると言っているのはなぜですか?

(私は低レベルのプログラミングの初心者なので、皆さんからもっと学びたいと思います)

42
user188276

完全にするために、「どのような構造が線形時間でアクセスされますか?」 Linked List 構造は線形時間でアクセスされます。 n要素を取得するには、n-1以前の要素を移動する必要があります。テープレコーダーやVHSカセットのように、テープ/ VHSの最後に移動するには、長い時間待たなければなりませんでした:-)

アレイはハードディスクに似ています。すべてのポイントに「一定の」時間でアクセスできます:-)

これが、コンピュータのRAMがRAM:ランダムアクセスメモリと呼ばれる理由です。その場所の前のすべてのメモリを経由せずにアドレスがわかっている場合は、その場所に移動できます。

一部の人から、HDアクセスは実際には一定の時間内にあるわけではないと言われました(アクセスとは、「ヘッドを配置してHDの1つのセクターを読み取る時間」を意味します)。よくわかりません。私はググってみましたが、それについて話す人を見つけられませんでした。ランダムにアクセスされるため、時間が線形ではないことを知っています。最後に、HDアクセスが十分に安定していないと思われる場合(ただし、定数、RAMのアクセス、キャッシュ、プリフェッチ、データの局所性、およびコンパイラの最適化を考慮して?)、自由に文を検討してください。 as配列はUSBディスクスティックに似ています。すべてのポイントに「一定の」時間でアクセスできます:-)

14
xanatos

配列は、事実上、メモリ位置(ポインタ)によって認識されます。 _a[3]_へのアクセスは、location_of_a + 3 * sizeof(int)なので、一定の時間で見つかります。

Cでは、これを直接見ることができます。 _a[3]_は*(a+3)と同じであることを覚えておいてください。これは、何をしているのか(ポインタ "3項目"を逆参照する)の点で少し明確です。

24
Reed Copsey

インデックス0から9までの10個の整数変数の配列は、メモリアドレス2000、2004、2008、…2036に10ワードとして格納されるため、インデックスiの要素のアドレスは2000 + 4×iになります。このプロセスは1つの乗算と1つの加算を必要とします。これらの2つの演算には一定の時間がかかるため、アクセスは一定の時間で実行できると言えます

17
user3013127

「一定の時間」とは、実際には「「問題のサイズ」に依存しない時間」を意味します。 「問題」「コンテナーから何かを取得」の場合、「問題サイズ」はコンテナーのサイズです。

配列の要素へのアクセスには、コンテナのサイズに関係なく、基本的に同じ時間がかかります(これは単純化です)。固定された一連のステップが要素の取得に使用されるため、メモリ内の位置(これも単純化です)が計算されます。次に、メモリ内のその場所の値が取得されます。

たとえば、リンクされたリストはこれを行うことができません。各リンクが次のリストの場所を示しているためです。要素を見つけるには、前の要素をすべて処理する必要があります。平均して、コンテナーの半分まで作業するので、コンテナーのサイズは明らかに重要です。

8
Karl Knechtel

配列はメモリに順番に格納されるためです。したがって、実際には、array [3]にアクセスすると、「配列の先頭のメモリアドレスを取得し、それに3を追加して、その場所にアクセスします」とコンピュータに伝えます。追加には一定の時間がかかるため、配列へのアクセスもそうです!

6
Phil

配列は、同様のタイプのデータのコレクションです。したがって、すべての要素は同じ量のメモリを使用します。したがって、配列のベースアドレスとそれが保持するデータのタイプがわかっている場合は、以下の式を使用して、一定の時間で要素Array [i]を簡単に取得できます。

int takes 4 bytes in a 32 bit system.
int array[10];
base address=4000;
location of 7th element:4000+7*4.
array[7]=array[4000+7*4];

したがって、そのベースアドレスと保持しているデータのタイプがわかっていれば、その要素を明確に表示して、一定の時間でi番目の要素を取得できます。配列データ構造の詳細については、 this リンクにアクセスしてください。

3
Sunil Kumar Jha

アクセスする必要があるメモリ位置がわかっている場合、このアクセスは一定時間内に行われます。配列の場合、メモリ位置は、ベースポインター、要素のインデックス、要素のサイズを使用して計算されます。これには、実行に一定の時間がかかる乗算および加算演算が含まれます。したがって、配列内の要素アクセスには一定の時間がかかります。

1

配列はシーケンシャルです。つまり、配列内の次の要素のアドレスは、現在の要素の隣にあります。したがって、配列の5番目の要素を取得する場合は、配列のベースアドレスを5と合計して5番目の要素のアドレスを計算します。この直接アドレスは、そのアドレスで要素を取得するために直接使用されるようになりました。

ここでさらに同じ質問をすることができます-「コンピューターはどのようにして計算されたアドレスを直接認識/アクセスしますか?」これが、コンピュータメモリ(RAM)の性質と原理です。 RAMが一定の時間に任意のアドレスにアクセスする方法にさらに興味がある場合は、任意のコンピューター組織のテキストで見つけることができます。または単にそれをグーグルできます。

1