プログラムで利用する便利な配列、これをコンピュータサイエンスの視点から理解しましょう。
汎用的な知識を得ることで、効率のいいコードが書けたり、別のプログラミング言語を学ぶ時の役に立ちます。
配列 (array) の概念
配列は変数の集合です。例えばユーザー4人の年齢を管理する場合、変数を4つ用意しても実現できますが、それでは使い勝手が悪いです。
なので1つだけ変数を作ってアドレス値を管理、そのアドレス値を起点に複数個のデータを管理するのが配列です。
配列とメモリの関係
変数と同じく配列にもメモリが割り当てられます。仮に1byteのデータを4つ確保したい場合、1byte x 4個で4byteの領域が確保されます。
1つ2byteのデータであれば、2byte x 4個で8byteの領域になります。1つだけ違うサイズで確保するとかは出来ません。
配列のアドレス値
個数分の領域が確保されてるのにアドレス値が1つしかありません。では、どうやってアクセスするのでしょうか。
簡単です。1つ単位のデータサイズは固定されてるので、1つ分だけアドレス値を進めれば次のデータを示せます。
アドレス値でアクセスするの大変じゃないの?
そのためにインデックスって呼ばれる仕組みがあるよ。
インデックス (index)
これは変数名[0]とか変数名[4]みたいに、アドレス値を使わずに配列の各領域にアクセスする方法です。
日本語で添字と呼ばれることもあります。インデックスは0を開始として、最後は個数-1になります。
そして変数名がアドレス値の起点になり、インデックスの値だけアドレス値がズレます。これをオフセットと言います。
なんで0が開始なの?
アドレス値との関係だと思う。例えば0x00000000が起点だとして、そこに1つ目のデータがあるよね。
これを1番目のインデックスにした場合、0x00000000 + 1で2つ目のデータを指しちゃうからかな。
様々な種類の配列
配列にも種類があります。有名どころを紹介するので、参考にしてください。
多次元配列 (multidimensional array)
これは配列の要素がさらに階層化されてる配列です。実は先程の配列も1次元配列と言います。
この多次元配列は少し分かりづらいので例を使って説明します。
ある学校に1クラス3人、それが2クラスあるとします。
この時に生徒の年齢を管理したい場合、どんな構造が適切でしょうか?
より正確に言うなら、どうやって個別の生徒にアクセスしたいと思いますか。
クラス名や生徒名でアクセスしたいです。
そうだよね。つまりは要素(クラス名)の要素(生徒名)、インデックスが階層化された構造を使えばいいんだよ。
そうなってる配列を多次元配列って言うんだ。階層数に制限はなく、理論の話をすれば無限に階層化できるよ。
ポイントは要素数だね。1次元配列と同じで、ある要素だけ別サイズは駄目なんだ。
仮に1クラスだけ生徒数が多い場合、そのサイズが生徒数を表現する階層の要素数になるよ。
各要素にはどうやってアクセスするんですか?
変数名[0][2]とか変数名[0,2]みたいに複数のインデックスを使ってアクセスするよ。
連想配列 (associative array)
種類と言うよりインデックスの考え方の違いです。
普通の配列が0や1の数値をインデックスに使うのに対し、連想配列は文字列などの数値以外のデータを利用します。
とは言え、これはプログラミング言語の話であって、最終的にはアドレス空間の領域にアドレス値でアクセスします。
めんどくさいのは利用可否や仕様が言語単位で変わること。そもそも僕は連想配列って単語自体も使ってません。
これは利用する言語によると思いますが、ここではそんな配列があるくらいの認識でいいです。
ジャグ配列 (jagged array)
これは配列の要素に配列が入ってる配列です。
配列の..配列の..配列? もしかして頭の体操?
僕も書いててそう思ったけど、そのままの意味なんだ。配列が表現する各要素が配列になってるんだよ。
それって多次元配列と何が違うんですか?
多次元配列と違って下位の階層に存在する配列の要素数が一致してないんだ。
これのメリットをさっきの学校を例に説明するなら、生徒数が変化しても最適なサイズを確保できるよ。
ちなみにこれ、普通はこんな綺麗なメモリ配置になりません。これは現実的にはポインタや参照という概念を使って表現されるからです。
この仕組みは要素内の各配列がメモリ上の遥か彼方、どこかに存在して、メインの配列はそれを示す参照値を所有します。
先生! 何を言ってるのか分かりません。
説明の画像を用意してるけど、ポインタや参照は難しいから駄目なら気にしなくていいよ。
覚えて欲しいのは、ジャグ配列は要素がバラバラの配列ってことだよ。
配列のメリットとデメリット
配列のメリットは効率と速度です。1つの変数で複数の値を管理できるため効率的なコードが書けます。
加えて速度が圧倒的に早いです。それもそのはず、アドレス値を+1オフセットすれば次のデータなので爆速です。
では、デメリットは何でしょうか。それは配列の作成後にサイズを変更できないことです。
勘違いしないように補足すると、プログラミング言語によってはサイズの変更が可能です。
しかし、配列は元々想定されたサイズを最適に利用するための機能であり、後に可変する要素には適しません。
その場合はリストと呼ばれる最適解が存在するので、そっちを利用してください。
プログラムで利用するリスト構造、これをコンピュータサイエンスの視点から理解しましょう。汎用的な知識を得ることで、効率のいいコードが書けたり、別のプログラミング言語を学ぶ時の役に立ちます。 リスト (list) の概念 リストも配列と同じく複数個のデータを扱えますが実体は大きく異なります。根本的に違うのはメモリ上に連続して確保されないことでしょう。これがリストの大きな特徴になり、配列と比べてメリットもあればデメリットも存在します。では、それらについて順番に理解しましょう。 リスト...
せっかくなので追加で学びましょう。なぜ、配列は要素の追加に不適切なのでしょうか。
ここで次の画像を見てください。この状態で領域のサイズを拡大できますか?
無理だと思います。
その通り。追加したくても増加分のアドレス値に別の値が存在するよね。
配列は繋がった領域を利用するから、空いてない場合は増やせないよ。
でも、可能な言語もあるんですよね?
うん。その時の解決策はシンプルだよ。今ある配列を別の領域に全部コピーするんだ。
そうすれば新しく拡大された領域が作れるよね。ただ、言うまでもなく無駄な処理に感じない?
すごく効率悪そうです。
そう。だから配列の要素を後から増やすべきではないんだ。
POINT配列は要素数が固定の場合に使うのが望ましい。
あとがき
プログラミング言語で学習するとコードの書き方を重視しちゃいませんか?
こういった基礎知識を覚えておくと、別の言語でもサクッと理解できて便利ですよ。
◆ コンピュータサイエンスに関する学習コンテンツ
この記事は参考になりましたか?
コメント