データ構造 (配列・リスト)

配列と連結リストの仕組み・違い・計算量を、身近なたとえで整理。動的配列や多次元配列も押さえる。

編集・検証: ITパスポートスタディ編集部 公式情報: IPA ITパスポート試験公式ページ 制作・検証方針

たくさんのデータをコンピュータの中でどう並べておくか。その「しまい方」のルールがデータ構造です。代表選手である配列とリストの違い、そして計算量の考え方を、身近なたとえから整理していきましょう。

星見 めい(普段) 星見 めい

先生、データ構造ってよく聞くけど、要するにデータの入れ物のことでしょ?

紫垣 こはる 先生(笑顔) 紫垣 こはる 先生

入れ物というより、入れ物の中の並べ方のルール、と言ったほうが近いわね。
同じデータでも、どう並べるかで使い勝手がガラッと変わるのよ。

紫垣 こはる 先生(普段) 紫垣 こはる 先生

まず基本中の基本が配列よ。
マンションの部屋みたいに、同じ大きさの箱がぴったり連続して並んでいるの。

小夜川 ほのか(普段) 小夜川 ほのか

マンションだと…101号室、102号室、って番号がついてますよねぇ?

蜂谷 まこと(普段) 蜂谷 まこと

まさにそれです。
その部屋番号にあたるのが添字(インデックス)ですね。
補足すると、多くの言語で添字は1ではなく0から始まります。

星見 めい(びっくり) 星見 めい

え、1番目が0なの? なんか気持ち悪いんだけど。

紫垣 こはる 先生(笑顔) 紫垣 こはる 先生

ふふ、最初は戸惑うわよね。
でもこれには理由があるの。
配列は先頭の住所(アドレス)から『何個ぶんずれた所か』で位置を計算するから、先頭そのものは『0個ずれ』なのよ。

蜂谷 まこと(普段) 蜂谷 まこと

だから添字を指定すれば、何番目でも一発で位置がわかる。
これをランダムアクセスと呼びます。
3000番目でも1番目と同じ速さで取り出せます。

小夜川 ほのか(普段) 小夜川 ほのか

わぁ、便利ですぅ。
じゃあ配列だけあれば十分なのではぁ…?

紫垣 こはる 先生(普段) 紫垣 こはる 先生

それが、そうもいかないのよ。
配列には弱点があってね。
途中にデータを差し込んだり、消したりするのが大変なの。

星見 めい(普段) 星見 めい

なんで? 1個入れるだけじゃん。

紫垣 こはる 先生(笑顔) 紫垣 こはる 先生

満員の映画館を想像してみて。
前のほうの席に1人割り込ませようとしたら、後ろの人が全員ひとつずつ席をずれないといけないでしょう?

星見 めい(笑い) 星見 めい

あー、マジか。
それは面倒くさいやつだ。

蜂谷 まこと(普段) 蜂谷 まこと

そこで登場するのが連結リスト(リンクトリスト)です。
各データが、次のデータの居場所メモ(ポインタ)を持っていて、数珠つなぎになっています。

小夜川 ほのか(笑顔) 小夜川 ほのか

宝探しみたいですねぇ。
『次はあそこだよ』ってメモを辿っていく感じなのぉ?

蜂谷 まこと(笑顔) 蜂谷 まこと

いい例えです。
だから挿入や削除は、前後のメモの行き先を書き換えるだけ。
席をずらす必要がありません。

星見 めい(びっくり) 星見 めい

じゃあ連結リストのほうが強いじゃん!

紫垣 こはる 先生(普段) 紫垣 こはる 先生

ところが、こちらにも弱点があるの。
連結リストは添字でいきなり飛べないのよ。
100番目が欲しければ、先頭から99回メモを辿るしかないの。

星見 めい(普段) 星見 めい

あー、なるほど。
どっちも一長一短、トレードオフってやつだね。

蜂谷 まこと(普段) 蜂谷 まこと

それを数値で表したのが計算量です。
配列のアクセスは件数によらず一定なので O(1)、連結リストは件数ぶん辿るので O(n)。
挿入・削除はちょうど逆になります。

小夜川 ほのか(しょんぼり) 小夜川 ほのか

おぉ…数字の n が出てくると急に難しく見えますぅ。

紫垣 こはる 先生(笑顔) 紫垣 こはる 先生

大丈夫よ。
O(1)は『データが何個あっても手間は変わらない』、O(n)は『データが増えた分だけ手間も増える』。
それだけ覚えておけば十分。

星見 めい(普段) 星見 めい

ところで先生、Pythonのリストって、配列なの? 連結リストなの?

紫垣 こはる 先生(笑顔) 紫垣 こはる 先生

いい質問。
実はそのどちらでもなくて、両者のいいとこ取りをした動的配列という仲間なの。

蜂谷 まこと(普段) 蜂谷 まこと

中身は配列なので添字アクセスは O(1) と速い。
でも要素が増えて満杯になると、自動で大きな箱を作り直して引っ越してくれます。
JavaのArrayListも同じ仲間ですね。

小夜川 ほのか(びっくり) 小夜川 ほのか

へぇ〜。
サイズを気にせず追加できるのは、裏でこっそり引っ越してくれてたからなんですねぇ!

紫垣 こはる 先生(普段) 紫垣 こはる 先生

ちなみに、最初からサイズが固定で変えられない配列は静的配列と呼ぶわ。
動的配列と対で覚えておくといいわよ。

蜂谷 まこと(普段) 蜂谷 まこと

あと試験では多次元配列も出ます。
1次元が一列の名簿なら、2次元は縦横のある表、と考えると分かりやすいです。

星見 めい(普段) 星見 めい

結局、自分でプログラム書くときはどれを選べばいいわけ?

蜂谷 まこと(普段) 蜂谷 まこと

普段はPythonのlistのような動的配列でほぼ困りません。
連結リストは、頻繁に途中の出し入れをする特殊な場面で選ばれる程度です。

紫垣 こはる 先生(笑顔) 紫垣 こはる 先生

まとめるわね。
配列は『番地で一発アクセス、でも割り込みは苦手』、連結リストは『割り込み得意、でも頭から辿るのは苦手』。
この対比と、添字アクセスが O(1) という点を押さえれば、試験はばっちりよ。

確認クイズ

配列の要素に添字(インデックス)で直接アクセスする場合の計算量として正しいものはどれか。

  1. O(1)
  2. O(log n)
  3. O(n)
  4. O(n²)
こたえを見る

正解: 1. O(1)

正解はO(1)(定数時間)。配列はメモリ上に連続して格納されているため、先頭アドレス+添字×要素サイズで位置を即座に計算でき、要素数に関係なく一定時間でアクセスできます。O(log n)は二分探索など、O(n)は連結リストのように先頭から順に辿る場合、O(n²)は二重ループの処理などにあたり、いずれも配列の添字アクセスには当てはまりません。

🔖 この記事の関連書籍

Amazonアソシエイトリンクを含みます。他分野は おすすめ書籍ページ へ。