アルゴリズムとデータ構造 補足資料11-2 「線形リスト」 横浜国立大学 理工学部 数物・電子情報系学科 富井尚志 メモリの「物理的」特性を考慮して、 「論理的」に扱う方法 • 物理特性:Random Access Memory (RAM) – 「アドレス」と「中身」:有限個のセル(資源) – CPUのメモリ操作:アドレス指定による読み出し、書き込み • それなりに遅い(あまりデータを動かしたくない) • 論理的に扱う – 「みなす」 • OSに、メモリ領域を管理させる。(使うときに「割当て」、終わったら 「解放」) • 「ポインタ」を使って、「指し示している」とみなす • メモリ内では、データは極力移動しない。「割当て」「解放」を、アド レスを指定して行う。 – 物理的にはこうなっているものを、こうであると考える(「み なす」) アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … 0x 40ea 0800 key 0x 40ea 0804 next 0x 40ea 0810 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 key 0x 40ea 0814 next 0x 0000 0000 0x 40ea 0820 0x 0100 0001 0x 40ea 0824 0x 1011 0111 0x 40ea 0828 0x 0100 0001 0x 40ea 082c key 0x 40ea 0830 next mallocで 確保された領域 0x 40ea 0800 0x 0110 1111 0x 40ea 0838 0x 1010 0111 0x 40ea 083c 0x 0101 0000 … 変数 21 0x 40ea 0834 … どのような状況か? 0x 40ea 082c p 0x 40ea 081c 構成 23 0x 0000 0000 0x 40ea 0818 物理的 22 0x 40ea 0808 0x 40ea 0810 メモリの ※ mallocは、そのときそのときで 適当な場所を割り当てる。 アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … 0x 40ea 0800 key 0x 40ea 0804 next 0x 40ea 0810 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 key 0x 40ea 0814 next 0x 0000 0000 0x 40ea 0820 0x 0100 0001 0x 40ea 0824 0x 1011 0111 0x 40ea 0828 0x 0100 0001 0x 40ea 082c key 0x 40ea 0830 next 21 0x 40ea 0800 0x 40ea 0834 0x 0110 1111 0x 40ea 0838 0x 1010 0111 0x 40ea 083c 0x 0101 0000 … … 変数 0x 40ea 082c p 0x 40ea 081c どのような状況か? 23 0x 0000 0000 0x 40ea 0818 物理的 22 0x 40ea 0808 0x 40ea 0810 メモリの mallocで 確保された領域 構成 アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … 0x 40ea 0800 key 0x 40ea 0804 next 0x 40ea 0810 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 key 0x 40ea 0814 next 0x 0000 0000 0x 40ea 0820 0x 0100 0001 0x 40ea 0824 0x 1011 0111 0x 40ea 0828 0x 0100 0001 0x 40ea 082c key 0x 40ea 0830 next 21 0x 40ea 0800 0x 40ea 0834 0x 0110 1111 0x 40ea 0838 0x 1010 0111 0x 40ea 083c 0x 0101 0000 … … 変数 0x 40ea 082c p 0x 40ea 081c どのような状況か? 23 0x 0000 0000 0x 40ea 0818 物理的 22 0x 40ea 0808 0x 40ea 0810 メモリの mallocで 確保された領域 構成 アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … 0x 40ea 0800 key 0x 40ea 0804 next 0x 40ea 0810 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 key 0x 40ea 0814 next 0x 0000 0000 0x 40ea 0820 0x 0100 0001 0x 40ea 0824 0x 1011 0111 0x 40ea 0828 0x 0100 0001 0x 40ea 082c key 0x 40ea 0830 next 21 0x 40ea 0800 0x 40ea 0834 0x 0110 1111 0x 40ea 0838 0x 1010 0111 0x 40ea 083c 0x 0101 0000 … … 変数 0x 40ea 082c p 0x 40ea 081c どのような状況か? 23 0x 0000 0000 0x 40ea 0818 物理的 22 0x 40ea 0808 0x 40ea 0810 メモリの mallocで 確保された領域 構成 論理的 データ構造の key 22 next key next 構成 どのような状況か? 23 NULL 変数 p mallocで 確保された領域 key 21 next 論理的には「指し示している」ので、見やすくするために図示を工夫。 物理的にメモリ内で「データが移動」しているわけではない。 論理的 p データ構造の key 22 next key next 構成 どのような状況か? 23 NULL 変数 mallocで 確保された領域 key 21 next 論理的には「指し示している」ので、見やすくするために図示を工夫。 物理的にメモリ内で「データが移動」しているわけではない。 論理的 p データ構造の key 構成 22 next どのような状況か? key next key next 変数 mallocで 確保された領域 21 23 NULL 論理的 p データ構造の 構成 どのような状況か? key 22 next key next key next 変数 mallocで 確保された領域 21 23 NULL 論理的 p データ構造の 構成 どのような状況か? key 21 next key 22 next key next 変数 mallocで 確保された領域 23 NULL 論理的 データ構造の 構成 どのような状況か? p key next 21 key next 22 key next 23 NULL 線形リスト 変数 mallocで 確保された領域 アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … 0x 40ea 0800 key 0x 40ea 0804 next 0x 40ea 0810 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 key 0x 40ea 0814 next (こういう状態であると「みなす」)↓ 0x 0000 0000 p 0x 40ea 082c p 0x 40ea 081c 論理構成 23 0x 0000 0000 0x 40ea 0818 (実際のメモリの状態) 22 0x 40ea 0808 0x 40ea 0810 物理構成 ← 0x 40ea 0820 0x 0100 0001 key 0x 40ea 0824 0x 1011 0111 next 0x 40ea 0828 0x 0100 0001 0x 40ea 082c key 0x 40ea 0830 next 21 0x 40ea 0800 0x 40ea 0834 0x 0110 1111 0x 40ea 0838 0x 1010 0111 0x 40ea 083c 0x 0101 0000 … … 線形リスト 21 key 22 next key next 23 NULL アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … 0x 40ea 0800 key 0x 40ea 0804 next 22 0x 40ea 0810 0x 40ea 0808 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 0x 40ea 0810 key 0x 40ea 0814 next 0x 0000 0000 0x 40ea 0820 newp 0x 0100 0001 key 0x 1011 0111 next 21 0x 0100 0001 0x 40ea 0828 0x 40ea 082c key 0x 40ea 0830 next 21 0x 40ea 0800 0x 40ea 0834 0x 0110 1111 0x 40ea 0838 0x 1010 0111 0x 40ea 083c 0x 0101 0000 … p 0x 40ea 082c p 0x 40ea 081c 0x 40ea 0824 23 0x 0000 0000 0x 40ea 0818 ここで、新たに要素を追加したい (ただし、変数newpをつかってよい) … key 22 next key next 23 NULL アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … ① newp用にメモリ確保 0x 40ea 0800 key 0x 40ea 0804 next 22 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 0x 40ea 0810 key 0x 40ea 0814 next 0x 0000 0000 newp 0x 0100 0001 key 0x 1011 0111 next 21 0x 0100 0001 0x 40ea 0828 0x 40ea 082c key 0x 40ea 0830 next 21 0x 40ea 0800 0x 40ea 0834 0x 0110 1111 0x 40ea 0838 0x 1010 0111 0x 40ea 083c 0x 0101 0000 … p 0x 40ea 082c p 0x 40ea 0820 0x 40ea 0824 23 0x 0000 0000 0x 40ea 0818 newp = (struct list *)malloc(sizeof(struct list)); 0x 40ea 0810 0x 40ea 0808 0x 40ea 081c ここで、新たに要素を追加したい (ただし、変数newpをつかってよい) … key 22 next key next 23 NULL アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … ① newp用にメモリ確保 0x 40ea 0800 key 0x 40ea 0804 next 22 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 0x 40ea 0810 key 0x 40ea 0814 next newp next 0x 0000 0000 p 0x 0100 0001 key 0x 40ea 0834 next 21 0x 0100 0001 0x 40ea 0828 21 0x 40ea 082c key 0x 40ea 0830 next 0x 40ea 0800 0x 40ea 0834 key 0x 0110 1111 0x 40ea 0838 next 0x 1010 0111 0x 0101 0000 0x 40ea 083c … key 0x 40ea 082c p 0x 40ea 0820 0x 40ea 0824 newp 23 0x 0000 0000 0x 40ea 0818 newp = (struct list *)malloc(sizeof(struct list)); 0x 40ea 0810 0x 40ea 0808 0x 40ea 081c ここで、新たに要素を追加したい (ただし、変数newpをつかってよい) … key 22 next key next 23 NULL アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … ② 確保した領域に値を代入 0x 40ea 0800 key 0x 40ea 0804 next 0x 40ea 0810 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 0x 40ea 0810 key 0x 40ea 0814 next newp next 0x 0000 0000 p 0x 0100 0001 key 0x 40ea 0834 next 21 0x 0100 0001 0x 40ea 0828 0x 40ea 082c key 0x 40ea 0830 next 0x 40ea 0834 key 0x 40ea 0838 next 21 0x 40ea 0800 … key 22 next 30 0x 1010 0111 0x 0101 0000 0x 40ea 083c … 30 key 0x 40ea 082c p 0x 40ea 0820 0x 40ea 0824 newp 23 0x 0000 0000 0x 40ea 0818 newp ->key = 30; 22 0x 40ea 0808 0x 40ea 081c ここで、新たに要素を追加したい (ただし、変数newpをつかってよい) key next 23 NULL アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … ③確保した領域からリストに接続 0x 40ea 0800 key 0x 40ea 0804 next 0x 40ea 0810 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 0x 40ea 0810 key 0x 40ea 0814 next newp next 0x 0000 0000 p 0x 0100 0001 key 0x 40ea 0834 next 21 0x 0100 0001 0x 40ea 0828 0x 40ea 082c key 0x 40ea 0830 next 0x 40ea 0834 key 0x 40ea 0838 next 21 0x 40ea 0800 … key 22 next 30 0x 40ea 082c 0x 0101 0000 0x 40ea 083c … 30 key 0x 40ea 082c p 0x 40ea 0820 0x 40ea 0824 newp 23 0x 0000 0000 0x 40ea 0818 newp ->next = p; 22 0x 40ea 0808 0x 40ea 081c ここで、新たに要素を追加したい (ただし、変数newpをつかってよい) 値(アドレス:ポインタ) をコピー key next 23 NULL アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … ここで、新たに要素を追加したい (ただし、変数newpをつかってよい) ③確保した領域からリストに接続 0x 40ea 0800 key 0x 40ea 0804 next 0x 40ea 0810 0x 40ea 0808 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 0x 40ea 0810 key 0x 40ea 0814 next newp ->next = p; 22 newp 23 ここがポイント! 0x 40ea 0820 0x 40ea 0824 newp 0x 0100 0001 key 0x 40ea 0834 next 21 0x 0100 0001 0x 40ea 0828 0x 40ea 082c key 0x 40ea 0830 next 0x 40ea 0834 key 0x 40ea 0838 next 21 0x 40ea 0800 … key 22 next 30 0x 40ea 082c 0x 0101 0000 0x 40ea 083c … → p 0x 40ea 082c p 0x 40ea 081c next 0x 0000 0000 0x 0000 0000 0x 40ea 0818 30 key 値(アドレス:ポインタ) をコピー key next 23 NULL アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … ④リストの先頭を改める 0x 40ea 0800 key 0x 40ea 0804 next 0x 40ea 0810 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 0x 40ea 0810 key 0x 40ea 0814 next newp next 0x 0000 0000 p 0x 0100 0001 key 0x 40ea 0834 next 21 0x 0100 0001 値(アドレス:ポインタ) 0x 40ea 0828 0x 40ea 082c key 0x 40ea 0830 next 0x 40ea 0834 key 0x 40ea 0838 next 21 0x 40ea 0800 … をコピー key 22 next 30 0x 40ea 082c 0x 0101 0000 0x 40ea 083c … 30 key 0x 40ea 0834 p 0x 40ea 0820 0x 40ea 0824 newp 23 0x 0000 0000 0x 40ea 0818 p = newp; 22 0x 40ea 0808 0x 40ea 081c ここで、新たに要素を追加したい (ただし、変数newpをつかってよい) key next 23 NULL アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … ここで、新たに要素を追加したい (ただし、変数newpをつかってよい) ④リストの先頭を改める 0x 40ea 0800 key 0x 40ea 0804 next p = newp; 22 0x 40ea 0810 0x 40ea 0808 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 newp ここがポイント!→ 0x 40ea 0810 key 0x 40ea 0814 next 0x 40ea 0820 newp 0x 0100 0001 key 0x 40ea 0834 next 21 0x 0100 0001 値(アドレス:ポインタ) 0x 40ea 0828 0x 40ea 082c key 0x 40ea 0830 next 0x 40ea 0834 key 0x 40ea 0838 next 21 0x 40ea 0800 … をコピー key 22 next 30 0x 40ea 082c 0x 0101 0000 0x 40ea 083c … p 0x 40ea 0834 p 0x 40ea 081c next 0x 0000 0000 0x 0000 0000 0x 40ea 0818 0x 40ea 0824 23 30 key key next 23 NULL アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … 完了! 0x 40ea 0800 key 0x 40ea 0804 next 22 0x 40ea 0810 0x 40ea 0808 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 0x 40ea 0810 key 0x 40ea 0814 next newp next 0x 0000 0000 p 0x 0100 0001 key 0x 40ea 0834 next 21 0x 0100 0001 0x 40ea 0828 0x 40ea 082c key 0x 40ea 0830 next 0x 40ea 0834 key 0x 40ea 0838 next 21 0x 40ea 0800 … key 22 next 30 0x 40ea 082c 0x 0101 0000 0x 40ea 083c … 30 key 0x 40ea 0834 p 0x 40ea 0820 0x 40ea 0824 newp 23 0x 0000 0000 0x 40ea 0818 0x 40ea 081c ここで、新たに要素を追加したい (ただし、変数newpをつかってよい) key next 23 NULL アドレス(32bit), 4 アドレス飛び 中身(1記憶単位=8bitを4領 域まとめて32bitで表示) … … 完了! 0x 40ea 0800 key 0x 40ea 0804 next 22 0x 40ea 0810 0x 40ea 0808 0x 41b7 41b0 0x 40ea 080c 0x 4c6f a750 0x 40ea 0810 key 0x 40ea 0814 next newp 30 key next 0x 0100 0001 key 0x 40ea 0834 next 21 0x 0100 0001 0x 40ea 0828 0x 40ea 082c key 0x 40ea 0830 next 0x 40ea 0834 key 0x 40ea 0838 next 21 0x 40ea 0800 … key 22 next 30 0x 40ea 082c 0x 0101 0000 0x 40ea 083c … 0x 0000 0000 0x 40ea 0834 p 0x 40ea 0820 0x 40ea 0824 p 23 0x 0000 0000 0x 40ea 0818 0x 40ea 081c ここで、新たに要素を追加したい key next 23 NULL ここで、新たに要素を追加したい (ただし、変数newpをつかってよい) 図で、もう1回。 p key next 21 key next 22 key next 23 NULL ここで、新たに要素を追加したい (ただし、変数newpをつかってよい) 図で、もう1回。 ① newp用にメモリ確保 newp = (struct list *)malloc(sizeof(struct list)); newp key next p key next 21 key next 22 key next 23 NULL ここで、新たに要素を追加したい (ただし、変数newpをつかってよい) 図で、もう1回。 ② 確保した領域に値を代入 newp ->key = 30; newp key 30 next p key next 21 key next 22 key next 23 NULL ここで、新たに要素を追加したい (ただし、変数newpをつかってよい) 図で、もう1回。 ③確保した領域からリストに接続 newp ->next = p; newp key 30 next p 値をコピー key next 21 key next 22 key next 23 NULL ここで、新たに要素を追加したい (ただし、変数newpをつかってよい) 図で、もう1回。 ④リストの先頭を改める p = newp; newp 値をコピー p key 30 next key next 21 key next 22 key next 23 NULL ここで、新たに要素を追加したい 図で、もう1回。 完了! p key next 30 key next 21 key next 22 key next 23 NULL メモリの「物理的」特性を考慮して、 「論理的」に扱う方法 • 物理特性:Random Access Memory (RAM) • 論理的に扱う:「割当て」「解放」「ポインタで指 し示す」 • 動的データ構造: プログラムが使うメモリ領 域を、必要に応じて増減させる。 – 配列「変数」は、そのスコープが有効な期間中 ずっと確保される。 – 動的「割当て」は、必要に応じて増減させる
© Copyright 2025 ExpyDoc