2 - 横浜国立大学

Download Report

Transcript 2 - 横浜国立大学

アルゴリズムとデータ構造
補足資料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)
• 論理的に扱う:「割当て」「解放」「ポインタで指
し示す」
• 動的データ構造: プログラムが使うメモリ領
域を、必要に応じて増減させる。
– 配列「変数」は、そのスコープが有効な期間中
ずっと確保される。
– 動的「割当て」は、必要に応じて増減させる