本文へスキップ
totonoe.tech

プログラミング言語を整える

中級

アルゴリズムを整える。

= 並べ替え・探し方・しまい方を図で

先に結論

アルゴリズムは「仕事の手順書」、データ構造は「データのしまい方」です。同じ結果でも、手順としまい方しだいで手間が何十倍も変わります。

たとえば1,000件から1件を探すとき、端から順に見ると最大1,000回、並んだデータを半分ずつ絞ると最大10回で済みます。下の3つの章で、それぞれ手を動かして確かめられます。

基本情報技術者試験(FE)の科目B は、擬似言語のプログラムを1行ずつ追う問題です。配列の添字が 1 から始まる点が Java(0 から)と違うので、図の添字の数え方に気をつけて読んでください。試験の分野ごとの道具は基本情報・ITパスポートの範囲マップにまとめています。

ソート:棒の高さで並べ替えを見る

数の並びを小さい順に整える手順がソートです。棒の高さが数の大きさ。1手ずつ進めて、いま何を比べ、何を入れ替えたのかを確かめます。

やり方

隣どうしを比べ、左が大きければ入れ替える。これを端から端まで繰り返すと、大きい値が右端に1つずつ落ち着く。

  • まだ
  • 比較「比」
  • 交換・書き込み「換」「書」
  • 最小候補「最」・ピボット「基」・取り出し「選」
  • 確定「✔」

比べた回数
0
動かした回数
0

動かした回数は、交換1回を1、配列への代入(ずらす・書き戻す)1回を1と数えます。同じ位置どうしは動かしていないので数えません。

疑似コード(バブルソート・光っている行がいま実行中)

 

a は配列、n は個数、swap(a, x, y) は a の x 番目と y 番目の入れ替え。コードの添字は Java と同じ0始まり。

同じデータで5つを走らせると

上で作ったデータをそのまま5つに渡したときの回数です。「データを作り直す」や並び方の切り替えで変わります。

同じデータで5つのソートを走らせたときの比較回数と動かした回数
やり方 比べた回数 動かした回数 比べた回数の目安

計算量(O 記法)の比べ表

O 記法は「データの個数 n が増えたとき、手間がどう増えるか」を表す書き方です。 n が2倍になると、O(n) の手間は2倍、O(n log n) は2倍より少し多く、O(n²) は4倍になります。 細かい係数は無視して、増え方の形だけを見ます。

個数 n に対する手間の目安
個数 n n(O(n)) n log₂n(約) n²(O(n²))
10 10 33 100
100 100 664 10,000
1,000 1,000 9,966 1,000,000
5つのソートの計算量・安定性・追加メモリ
やり方 最良 平均 最悪 安定 追加メモリ
バブルソート O(n) O(n²) O(n²) 安定 O(1)
選択ソート O(n²) O(n²) O(n²) 安定ではない O(1)
挿入ソート O(n) O(n²) O(n²) 安定 O(1)
クイックソート O(n log n) O(n log n) O(n²) 安定ではない O(log n)
マージソート O(n log n) O(n log n) O(n log n) 安定 O(n)
  • バブルソート 最良の O(n) は、交換がなければ途中で終える書き方をした場合。
  • 選択ソート 比較の回数はデータの並びによらない。交換は多くても n−1 回。
  • 挿入ソート ほぼ整列済みのデータでは比較が少なくて済む。
  • クイックソート ピボットの選び方が悪いと最悪になる(ここでは右端固定なので、整列済み・逆順で最悪)。追加メモリは再帰の深さ(最悪 O(n))。
  • マージソート 作業用の配列が n 個ぶん必要。

「安定」とは、同じ値が複数あるとき、並べ替えたあとも元の前後関係が保たれることです。 たとえば得点でソートしたあと、同点の人を元の名簿順のままにしておきたいときに関わります。

データ構造を手で動かす

データのしまい方には種類があり、得意なこと・苦手なことが違います。ボタンで操作すると、中で何が起きたかを 1 手ずつ図と言葉で見られます。

配列(同じ大きさの箱を横に並べる)

番号(添字)を言えば、一発でその箱の中身を取り出せる並びです。途中に 1 つ入れたいときは、後ろの全員を 1 つずつずらして場所をあける必要があります。

Java や C では添字は 0 から数えますが、基本情報技術者試験の科目Bの擬似言語では 1 から数えます。切り替えると、下の説明も擬似コードもその数え方に変わります。

擬似コード(実行中の行に ▶ が付きます)

 

得意なこと 添字で読む・書くのは 1 回で済みます(O(1))。メモリ上で隣り合って並ぶので、まとめて処理するのも速いです。

苦手なこと 途中への挿入・削除は後ろをずらすので、要素数に比例して手間が増えます(O(n))。大きさは作るときに決まります。

連結リスト(次のノードの場所を持つ鎖)

値と「次はここ」という矢印(ポインタ)をセットにしたノードを、鎖のようにつないだものです。途中に入れるときは、矢印を付け替えるだけでほかのノードは動きません。

擬似コード(実行中の行に ▶ が付きます)

 

得意なこと 先頭への挿入・削除は矢印の付け替えだけで済みます(O(1))。手前のノードが分かっていれば、途中でも付け替えは 2 本で済みます。

苦手なこと n 番目を読むにも、値を探すにも、先頭から順にたどる必要があります(O(n))。矢印を持つぶん、メモリも余分に使います。

スタック(積み上げて、上から取る)

本を積み重ねるように、入れるのも出すのもいちばん上だけです。最後に入れたものが最初に出てくるので、後入れ先出し(LIFO)と呼びます。ブラウザの「戻る」や、関数呼び出しの記録に使われます。

擬似コード(実行中の行に ▶ が付きます)

 

得意なこと push も pop も、動かすのは top の 1 か所だけです(O(1))。

苦手なこと 真ん中や底にあるものは、上のものを先に取らないと取り出せません。

キュー(並んだ順に出る行列)

お店の行列のように、入るのは後ろ、出るのは前です。先に入れたものが先に出るので、先入れ先出し(FIFO)と呼びます。印刷の順番待ちなどに使われます。

擬似コード(実行中の行に ▶ が付きます)

 

得意なこと enqueue も dequeue も、先頭と末尾の印を動かすだけです(O(1)。リング状の配列や連結リストで作った場合)。

苦手なこと 途中の要素を取り出すことはできません。順番どおりにしか出せません。

二分探索木(小さい値は左、大きい値は右)

各ノードが「左の子は自分より小さい、右の子は自分より大きい」という約束を守って並んだ木です。探すときは、比べるたびに半分近くを切り捨てて進めます。

擬似コード(実行中の行に ▶ が付きます)

 

得意なこと 木の形が整っていれば、探索・挿入・削除は段数に比例した回数で済みます(平均 O(log n))。中順で巡回すると昇順に取り出せます。

苦手なこと 昇順に入れ続けるなど木が一方に偏ると、連結リストと同じ並びになり O(n) まで遅くなります。

ハッシュテーブル(キーから置き場所を計算する)

キーをハッシュ関数に通して「この番号の箱に入れる」と計算で決める仕組みです。探すときも同じ計算をするので、全部を見て回る必要がありません。別々のキーが同じ番号になることを「衝突」と呼びます。

ハッシュ関数は「数字だけのキーは、その数を表の大きさで割った余り」「それ以外は、各文字の文字コードを足した合計を表の大きさで割った余り」と決めています。例: "AB" は 65 + 66 = 131、131 を 7 で割った余り 5。

擬似コード(実行中の行に ▶ が付きます)

 

得意なこと うまく散らばれば、入れる・探す・消すが 1 回の計算でほぼ済みます(平均 O(1))。

苦手なこと 衝突が増えると遅くなり、全部が同じ番号になると O(n) まで落ちます。キーを順番に取り出すのは苦手です。

このツールについて

並べ替え・探し方・データのしまい方を、ボタンで1手ずつ動かして、中で何が起きているかを図で確かめます。計算はすべてこの端末の中で行い、どこにも送信しません。

ソート5種・二分探索・データ構造6種を、ボタンで1手ずつ動かして図で確かめます。比べた回数・入れ替えた回数も数えます。言語は Java とあわせてどうぞ。

主な機能

  • 5つのソートを棒グラフで1手ずつ再生し、比較・交換の回数を数える
  • 計算量(O記法)の最良・平均・最悪・安定性を比べる表
  • 線形探索と二分探索の回数比べと、データ数ごとの最大回数
  • 配列・連結リスト・スタック・キュー・二分探索木を操作して図で確かめる
  • ハッシュテーブルの衝突処理(チェイニングとオープンアドレス)を切り替えて比べる

よくある質問

Q. アルゴリズムとデータ構造は何が違いますか?

A. アルゴリズムは「仕事の手順」、データ構造は「データのしまい方」です。たとえば二分探索という手順は、データが順番に並んでしまわれていて初めて使えます。両方をセットで考えます。

Q. O(n log n) のような書き方は何を表していますか?

A. データの数 n が増えたとき、手間がどのくらいの勢いで増えるかの目安です。O(n²) はデータが2倍になると手間が約4倍、O(n log n) は2倍強で済みます。細かい定数は省いて、増え方の形だけを比べます。

Q. どのソートを使えばよいですか?

A. 実務では言語の標準のソート(Java なら Arrays.sort や Collections.sort)を使います。ここで5つを比べるのは、手間の違いが生まれる理由を知り、試験や設計で計算量を判断できるようにするためです。

Q. 基本情報技術者試験(FE)の科目B 対策に使えますか?

A. 科目B はプログラムを1行ずつ追って変数の値を答える問題が中心です。ソートや二分探索、スタック・キュー・木の操作を1手ずつ動かして追う練習に使えます。FE の擬似言語では配列の添字が1から始まる点に注意してください。

Q. 二分探索はいつでも使えますか?

A. データが小さい順(または大きい順)に並んでいるときだけ使えます。並んでいないデータでは、先にソートするか、端から順に探す線形探索を使います。

入力値はURLの「#」以降に入るためサーバーには送信されません。リンクを開くと同じ状態を復元します。

続けて整える

このツールの解説記事

totonoe.tech を運営する株式会社Koinobori は、法人向けの研修サービス「NOBORIBA®」も運営しています。 ここで手を動かした内容を、講師から教わる形の研修です。このページの道具は無料のまま、登録もいりません。

運営サイト

私たちが運営するサイト