24
コンピュータサイエンス第2 データ構造 第5回

コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

コンピュータサイエンス第2データ構造

第5回

Page 2: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

データ構造

アルゴリズム設計の第⼀歩はデータ構造から▶リスト▶配列▶スタック▶キュー(待ち⾏列)▶⽊構造▶グラフ構造

Page 3: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

配列とリスト

配列▶同じ型のデータを決まった個数だけ並べたもの▶記憶装置の連続した番地に要素を並べたもの→ ランダムアクセス:どの要素にも同じ時間でアクセス

’a’ ’b’ ’c’ ’d’ ’e’ ’f’ ’g’ ’h’ ’i’

0 1 2 3 4 5 6 7 8配列 x

x[2]x + 要素サイズ× 2

x[5]x + 要素サイズ× 6

先頭アドレス+要素サイズ×インデックス

Page 4: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

配列とリスト

リスト▶配列同様データを並べたもの(同じ型のデータでなければならない場合もある.Pythonは異なっていてよい)▶データを⼊れた箱を参照でつないだもの→ 個数が決まっていない.挿⼊や削除が容易.→ 個々の要素の参照は配列ほど速くない.

リスト x

Pythonのリストは,x[2]やx[5]のように個々の要素にアクセスできるように⾒えるが,前から順にたどっている.

’a’ ’b’ ’c’ ’d’ ’e’

Page 5: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

スタックとキュースタック▶データの挿⼊と削除を⼀⽅の端でだけ⾏うという制限を加えたデータの並び(後⼊れ先出し:last-in-first-out,LIFO).▶配列やリストで実現できる(ここではリストを使⽤).→ プッシュ(push):

→ ポップ(pop):

’a’ ’b’ ’c’ ’d’ ’e’

’a’ ’b’ ’c’ ’d’ ’e’ ’f’

ʻfʼをプッシュ

’a’ ’b’ ’c’ ’d’ ’e’ ’f’

’a’ ’b’ ’c’ ’d’ ’e’

ʻfʼをポップ

トップ(top)

Page 6: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

スタックとキュースタック▶ Pythonによる実現:リストを利⽤.→ プッシュ:x = []x.append(’a’)x.append(’b’)x.append(’c’)

→ ポップ:x.pop()x.pop()y = x.pop()

Page 7: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

スタックとキューキュー(待ち⾏列)▶データを⼀⽅の端から挿⼊,もう⼀⽅の端から取出しを⾏う(先⼊れ先出し:first-in-first-out, FIFO).▶配列やリストで実現できる(ここではリストを使⽤).→ enqueue:

→ dequeue:

’a’ ’b’ ’c’ ’d’ ’e’

’a’ ’b’ ’c’ ’d’ ’e’ ’f’

ʻfʼをenqueue

’a’ ’b’ ’c’ ’d’ ’e’

’a’ ’b’ ’c’ ’d’ ’e’ ’f’ʻfʼをdequeue

tail

head

Page 8: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

スタックとキューキュー▶ Pythonによる実現:リストを利⽤.→ enqueue:x = []x.append(’a’)x.append(’b’)x.append(’c’)

→ dequeue:x.pop(0)x.pop(0)y = x.pop(0)

Page 9: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフグラフ構造▶節点(node)の集合と辺(edge)の集合からなる構造▶節点は○で,辺は○と○をつなぐ線あるいは⽮印で表す▶節点uと節点vをつなぐ辺を (u,v) と表す.▶辺に向きがあるグラフを有向グラフ,向きがないグラフを無向グラフという.

→ 有向グラフ:

→ 無向グラフ:

A

C

B

E

D

A

C

B

E

D

Page 10: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフ⽊構造▶グラフの⼀種.閉路がない無向グラフ.▶根となる節点を決めると⽊(根付き⽊)が定まる(有向グラフを⽤いて特定の根付き⽊を表すこともできる).

B C

A

D

E F

H I

G

親(parent)

葉(leaf)

根(root)

⼦(child)

内点(internal node)

祖先(ancestor)

⼦孫(descendant)深さ(depth)根からの辺の数:2

⾼さ(height):3

Page 11: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフ⽊の⾛査(traversal)▶深さ優先探索 ▶幅優先探索

B C

A

D

E F

H I

G

B C

A

D

E F

H I

G

Page 12: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフPython による⽊の実現▶式:( 1 + 2 ) * ( 3 – 4 / 5 ) を表す⽊→ リスト表現

1 2

4 5

/3

tree = ["*", ["+", 1, 2], ["-", 3, ["/", 4, 5] ]

Page 13: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフ深さ優先探索(depth first search)▶⽊の⾛査:節点を調べる順序→ 前順(pre-order)⾛査:親を調べてから⼦を調べる.

例:* + 1 2 - 3 / 4 5

→ 間順(in-order)⾛査:最初の⼦を調べ,親,残りの⼦を調べる.例:1 + 2 * 3 - 4 / 5

→ 後順(post-order)⾛査:⼦をすべて調べてから親を調べる.例:1 2 + 3 4 5 / - *

def preOrder (t):if type(t) == int:

print(t, end=" ")else:

print(t[0], end=" ")preOrder(t[1])preOrder(t[2])

def inOrder (t):if type(t) == int:

print(t, end=" ")else:

inOrder(t[1])print(t[0], end=" ")inOrder(t[2])

def postOrder (t):if type(t) == int:

print(t, end=" ")else:

postOrder(t[1])postOrder(t[2])print(t[0], end=" ")

Page 14: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフ幅優先探索(breadth first search)▶キューを⽤いた実現例:* + - 1 2 3 / 4 5

def bfs (t):q = []q.append(t)while (q != []):

n = q.pop(0)if type(n) == int:

print(n, end=" ")else:

print(n[0], end=" ")q.append(n[1])q.append(n[2])

Page 15: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフ2分探索⽊(binary search tree)▶各節点にデータがある.▶ある節点nの左側の⼦および⼦孫のデータは,nのデータより⼩さく,右側の⼦孫のデータは⼤きい.→各節点データと⽐較し,左右どちらかを調べればデータが⾒つかる.

8

2

9

15

10

12

25

20 30

例:12の探索

def search (a, key):if a == []:

return []elif a[0] > key:

return search(a[2], key)elif a[0] < key:

return search(a[3], key)else:

return a

Page 16: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフ2分探索⽊(binary search tree)▶挿⼊:探索後たどりついた節点の左右適切な⽅にぶらさげる.→各節点データと⽐較し,左右どちらかを調べればデータが⾒つかる.

8

2

9

15

10

12

25

20 30

例:11の挿⼊

11

Page 17: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフ2分探索⽊(binary search tree)▶挿⼊は,探索後たどりついた節点の左右適切な⽅にぶらさげる.→各節点データと⽐較し,左右どちらかを調べればデータが⾒つかる.

def insert (a, key, binding):if a == []:

return [key, binding, [], []]elif a[0] > key:

return [a[0], a[1], insert(a[2], key, binding), a[3]]elif a[0] < key:

return [a[0], a[1], a[2], insert(a[3], key, binding)]else:

return []

Page 18: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフ2分探索⽊(binary search tree)▶削除:指定のデータを探索し,削除する.削除後,辺をつなぎ合わせるときには,⼤⼩関係を保持.→削除する節点が葉:削除→削除する節点に1つだけ⼦があるとき:削除して,親に⼦をつなぐ.

→削除する節点に2つ⼦があったら? 8

2

9

15

10

12

25

20 30

例:12の削除

11

Page 19: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフ2分探索⽊(binary search tree)▶削除:指定のデータを探索し,削除する.→削除する節点に2つ⼦があるとき:削除する節点を右の最⼩(左の最⼤)の⼦孫で置き換える.

8

2

9

15

10

12

25

20 30

例:8の削除

9

2

15

10

12

25

20 30

Page 20: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフ2分探索⽊(binary search tree)▶ Pythonによる削除の実現

def delete (a, key):if a == []:

return aelif a[0] > key:

return [a[0],a[1],delete(a[2], key),a[3]]elif a[0] < key:

return [a[0],a[1],a[2],delete(a[3], key)]else:

if a[2] == []:return a[3]

elif a[3] == []:return a[2]

else:m = min (a)return [m[0], m[1], delete(a[2],m[0]), a[3]]

def min (a):if a == []:

return aelif a[2] == []:

return aelse:

return min(a[2])

Page 21: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフ⼀般的な(有向)グラフの表現※無向グラフは双⽅向に辺を引いた有向グラフ▶隣接⾏列

▶隣接リスト

21

43

1 1 1 00 1 0 10 1 1 10 0 0 1

1234

1 2 3 4

2 3

2 4

4

Page 22: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフ最短距離問題(Dijkstraのアルゴリズム)▶各節点の開始節からの最短距離を求める▶節点には開始節からの距離,辺には隣接節点間の距離が重み付けしてある.

▶アルゴリズム1. 最短距離が確定した節点の集合をV集合Uの節点には,V内を経由して到達する最短距離を与えておく.

2. U内の節点の中で最⼩の最短距離をもつ節点pを選び,Vに移す.

3. pを始点としてUに属する隣接節点の距離を更新する.

4. 2-3をUが空になるまで繰り返す.

B

AD

C E

F

2

1

3

3

4

6

6

Page 23: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフ最短距離問題(Dijkstraのアルゴリズム)▶データ表現 B

AD

C E

F

2

1

3

3

4

6

6

A = 0B = 1C = 2D = 3E = 4F = 5Infty = 10000

succ = [[B,C], # A[D], # B[E,F], # C[], # D[B,D], # E[] # F

]

edge = [ # A B C D E F [-1, 6, 4,-1,-1,-1], # A[-1,-1,-1, 3,-1,-1], # B [-1,-1,-1,-1, 3, 6], # C[-1,-1,-1,-1,-1,-1], # D[-1, 2,-1, 1,-1,-1], # E[-1,-1,-1,-1,-1,-1] # F

]

dist = [Infty]*len(succ)dist[A] = 0

出発点

Page 24: コンピュータサイエンス第2データ構造 アルゴリズム設計の第 歩はデータ構造から リスト 配列 スタック キュー(待ち 列) 構造 配列とリスト

⽊とグラフ最短距離問題(Dijkstraのアルゴリズム)▶アルゴリズムの実現 B

AD

C E

F

2

1

3

3

4

6

6

def dijkstra (q):if q == []:

return;else:

u = q.pop()min = Infty_q = []for n in q:

if dist[n] < min:_q.append(u)u = nmin = dist[u]

else:_q.append(n)

for s in succ[u]:if edge[u][s] + dist[u] < dist[s]:

dist[s] = edge[u][s] + dist[u]dijkstra (_q)

dijkstra ([A,B,C,D,E,F])