データ構造:解説つき練習問題

ヒントと解説つきの無料のデータ構造選択式練習問題。3 つのレベル:重要な用語と事実, 概念の応用, 事例と分析。

無料の練習問題やさしい

最大ヒープ性(max-heap property)とは何ですか。

次の問題 →
データ構造を無料で練習今すぐデータ構造を練習毎日 5 問まで無料。カード登録は不要です。

練習する内容

  1. やさしい重要な用語と事実
  2. ふつう概念の応用
  3. むずかしい事例と分析

データ構造をゼロから学ぶ

事前に学ぶこと: アルゴリズムと計算量

1データ構造とは

データ構造は、特定の操作(項目を探す、追加する、削除する)が速くなるように、メモリ上のデータを整理する方法です。

すべてに速い構造はありません。構造を選ぶことは、どの操作を安くするかを選ぶことです。そのコストは、n を項目数としてビッグオーで書きます。

基本的な構成要素は、配列と連結リストの 2 つです。

a7[0]3[1]9[2]4[3]7394∅h

配列は、項目を 1 つのメモリのかたまりに、順に並べて記憶します。コンピュータは i 番目の項目の位置を計算できるので、a[i] を読むのは O(1) です。先頭に挿入するには、すべての項目をずらす必要があります:O(n)。

連結リストは、各項目を、次のノードへのポインタをもつノードに記憶します。最後のポインタは null です。先頭(h)への挿入は、ポインタを 1 つ変えるだけです:O(1)。しかし、i 番目の項目に到達するには、i 個のポインタをたどる必要があります:O(n)。

双方向連結リストは、前のノードへのポインタももつので、両方向にたどれます。

セルフチェック 配列では O(1) だが、単方向連結リストでは O(n) になる操作はどれか。
  1. すべての項目を 1 回ずつ訪れる
  2. 先頭に新しい項目を挿入する
  3. 添字 i の項目を読む
  4. 項目を 1 つずつ数える

答え: 添字 i の項目を読む. 配列は i 番目の項目のアドレスを直接計算します。連結リストは、先頭から i 個のポインタをたどる必要があります。先頭への挿入は逆の場合です:リストでは安く、配列では高くつきます。

2スタックとキュー

スタックは皿の山のようなものです:追加も削除も一番上でだけ行います。最後に入れた項目が最初に出ます:LIFO。

  • push は項目を一番上に置き、pop は一番上の項目を取り除き、peek は取り除かずに一番上を読みます。いずれも O(1) です。
  • 用途:エディタの元に戻す機能、プログラムのコールスタック、括弧の対応の確認、深さ優先探索。

キューはレジの行列のようなものです:後ろに並び、前から出ていきます。最初に入れた項目が最初に出ます:FIFO。

  • enqueue は後ろに追加し、dequeue は前から取り除きます。どちらも O(1) です。
  • 用途:印刷ジョブ、処理待ちのメッセージ、幅優先探索。

デック(両端キュー)は、両端での追加と削除を認めます。優先度つきキューは、常に最も優先度の高い項目を先に取り出します。通常はヒープとして作られます。

セルフチェック テキストエディタの「元に戻す」ボタンに最も合うデータ構造はどれか。
  1. キュー
  2. グラフ
  3. スタック
  4. ハッシュ表

答え: スタック. 元に戻す操作は、最新の操作を最初に取り消さなければなりません:後入れ先出しです。キューでは、最も古い操作が最初に取り消されてしまいます。

3木、ヒープ、ハッシュ表、グラフ

木には、一番上のノードである根が 1 つあります。他のすべてのノードには、親がちょうど 1 つあります。子をもたないノードは葉です。n 個のノードをもつ木には、n − 1 本の辺があります。

二分木では、すべてのノードが最大 2 つの子をもちます。二分探索木(BST)はさらに規則を加えます:左の部分木のキーはそのノードより小さく、右の部分木のキーはそのノードより大きい。

BST の探索は、1 本の経路を下っていくので、O(高さ) かかります。平衡木(AVL 木、赤黒木)は、高さを log₂ n に近く保ちます。整列した順にキーを挿入すると、高さ n の鎖状になります。

ヒープは、すべての親が子より小さい(最小ヒープ)、または大きい(最大ヒープ)二分木です。最小値または最大値は根にあり、挿入と削除は O(log n) です。

ハッシュ表は、キーと値の組を記憶します。ハッシュ関数がキーを添字に変換するので、挿入と検索は平均で O(1) です。同じ添字になる 2 つのキーは衝突であり、チェイン法(スロットごとのリスト)やオープンアドレス法(別のスロットを試す)で解決します。

グラフは、辺で結ばれた頂点をもち、辺には向きや重みがあることもあります。隣接行列(メモリ O(V²))または隣接リスト(O(V + E))で記憶します。

セルフチェック キー 50、30、70、20、40 をこの順に、空の二分探索木に挿入する。30 の左の子は何か。
  1. 20
  2. 40
  3. 70
  4. 左の子はない

答え: 20. 20 は 50 より小さいので左の 30 に行き、30 よりも小さいのでもう一度左に行きます。40 は 30 より大きいので、30 の右の子になります。

4ステップごとの方法

課題を述べて、どの構造が合うかを問う問題や、いくつかの操作の後で構造がどうなっているかを問う問題がよくあります。

  1. 速くなければならない操作を見つけます:位置による参照、キーによる参照、最新の項目、最も古い項目、最小の項目、範囲のいずれか。
  2. それを構造に対応させます:添字 → 配列、キー → ハッシュ表、最新 → スタック、最も古い → キュー、最小または最大 → ヒープ、整列順や範囲 → 平衡探索木。
  3. 課題が必要とする他の操作のコストを、ビッグオーで確認します。
  4. 追跡問題では、操作を 1 つずつ実行し、そのたびに状態を書き留めます。
  5. 最終的な状態を、その構造の規則(LIFO、FIFO、BST の順序、ヒープの順序)に照らして確認します。

5例題

すべてのステップをたどりましょう。開く前に次のステップを予想してみましょう。

例題

キー 50、30、70、20、40、60 をこの順に、空の二分探索木に挿入する。中順走査の結果はどうなるか。また、60 の探索には何回の比較が必要か。

1

根を挿入する

最初のキー 50 が根になります。

2

30 と 70 を挿入する

30 は 50 より小さいので左に行きます。70 は 50 より大きいので右に行きます。

503070
3

20、40、60 を挿入する

20:50 より小さく、30 より小さいので、30 の左。40:50 より小さく、30 より大きいので、30 の右。60:50 より大きく、70 より小さいので、70 の左。

503070204060
4

中順に走査する

中順走査は、左の部分木、ノード、右の部分木の順に訪れます。

すると 20、30、40、50、60、70 になります:BST ではいつもそうであるように、キーが整列した順に並びます。

5

60 を探索する

50 と比べます:大きいので右へ。70 と比べます:小さいので左へ。60 と比べます:見つかりました。

503070204060

探索には、各レベルで 1 回ずつ、3 回の比較が必要です。

答え

中順:20, 30, 40, 50, 60, 70。60 の探索には 3 回の比較が必要です。

6よくある間違い

  • LIFO と FIFO を混同する。スタックは最新の項目を、キューは最も古い項目を返します。
  • 連結リストが添字による速いアクセスを与えると考える。先頭からたどらなければなりません。
  • BST が常に O(log n) だと考える。そうなるのは平衡木だけで、整列順の挿入では O(n) になります。
  • ハッシュ表の衝突を忘れる。O(1) は平均であり、最悪の場合ではありません。
  • 走査の種類を混同する。前順:ノードが先。中順:ノードが中央。後順:ノードが最後。
  • 大きな疎なグラフに隣接行列を使う。O(V²) のメモリを無駄にします。
セルフチェック 空のキューに 1、2、3 をこの順に enqueue する。最初の dequeue はどの項目を返すか。
  1. 1
  2. 1、2、3 のすべて
  3. 2
  4. 3

答え: 1. キューは先入れ先出しなので、1 が最初に出ます。3 はスタック(pop)の場合の答えで、スタックは最新の項目を返します。

7試験問題の例

  • やさしい:用語と事実。LIFO と FIFO、ノード・根・葉とは何か、BST の規則、ハッシュ関数の働き。
  • ふつう:概念の応用。課題に合う構造、push と pop や BST への挿入の結果、木の走査、線形探索法のハッシュ表、ビッグオーでのコスト。
  • むずかしい:事例と分析。平衡木、配列によるヒープ、B 木、トライ、素集合データ構造(union-find)、ブルームフィルタ、LRU キャッシュのような設計。

添字 0 から始まる配列に格納されたヒープでは、添字 i の子は 2i + 1 と 2i + 2 にあり、その親は ⌊(i − 1) / 2⌋ にあります。

アプリでステップごとに学ぶアプリでステップごとに学ぶ

例題

例題 1やさしい

静的配列と動的配列の主な違いは何ですか。

  1. A静的配列はインデックスによるアクセスが遅い
  2. B動的配列は、より大きなメモリブロックに移ることで拡張できる
  3. C動的配列は要素を連結されたノードに格納するので、1 つずつ拡張できる
  4. D静的配列は数値しか格納できない
ヒントを表示
  1. Python のリストや Java の ArrayList は、そのうちの一方の例です。
  2. 誤答を 2 つ消しました。残りの 2 つのうち 1 つが正解です。
答えと解説を表示

これが答えになる理由

静的配列のサイズは固定です。動的配列は満杯になると、より大きな配列を確保して要素をコピーします。

答え

B · 動的配列は、より大きなメモリブロックに移ることで拡張できる
例題 2ふつう

二分最小ヒープの extract-min はどのように動作しますか。

  1. A配列の最後の要素を取り除く
  2. B最後の要素を根に移し、下へ移動させる(sift down)
  3. C根を取り除き、すべての要素を 1 つ左にずらす
  4. Dすべての葉から新しい最小値を探す
ヒントを表示
  1. 木を完全に保ってから、順序を直します。
  2. 誤答を 2 つ消しました。残りの 2 つのうち 1 つが正解です。
答えと解説を表示

これが答えになる理由

最後の要素が根の穴を埋め、ヒープ性が成り立つまでより小さい子と交換されます。これには O(log n) かかります。

答え

B · 最後の要素を根に移し、下へ移動させる(sift down)
例題 3むずかしい

ランクによる合併(union by rank)も経路圧縮も使わない場合、n 要素の union-find 構造での 1 回の find の最悪コストはどれですか。

  1. AO(1)
  2. BO(α(n))
  3. CO(log n)
  4. DO(n)
ヒントを表示
  1. 木が退化することがあります。
  2. 誤答を 2 つ消しました。残りの 2 つのうち 1 つが正解です。
答えと解説を表示

これが答えになる理由

素朴な合併では木が長い鎖状につながることがあるので、find は n − 1 個の親ポインタをたどることがあります。2 つのヒューリスティックを使えば、ほぼ定数に近づきます。

答え

D · O(n)

質問と回答

データ構造とは?

すべてに速い構造はありません。構造を選ぶことは、どの操作を安くするかを選ぶことです。そのコストは、n を項目数としてビッグオーで書きます。

基本的な構成要素は、配列と連結リストの 2 つです。

データ構造はどう順を追って学ぶ?
  1. データ構造とは
  2. スタックとキュー
  3. 木、ヒープ、ハッシュ表、グラフ
  4. ステップごとの方法
  5. 例題
  6. よくある間違い
  7. 試験問題の例
データ構造の練習では何を学ぶ?
  • やさしい: 重要な用語と事実
  • ふつう: 概念の応用
  • むずかしい: 事例と分析

どの問題にも選択肢が 4 つあり、正解は 1 つだけです。 行き詰まったら、まず小さなヒントを開き、必要なときだけ詳しい解説を見ましょう。

練習のしかた

  • どの問題にも選択肢が 4 つあり、正解は 1 つだけです。
  • 行き詰まったら、まず小さなヒントを開き、必要なときだけ詳しい解説を見ましょう。
  • 進捗、間違えた問題、保存した問題は記録されるので、試験前に復習できます。

このトピックの前後のトピック

先に学ぶ

このトピックを含む科目

コンピュータサイエンスのほかのトピック

印刷用ワークシート

データ構造を無料で練習今すぐデータ構造を練習毎日 5 問まで無料。カード登録は不要です。