More Related Content More from Kenta Hattori (20) アルゴリズムとデータ構造53. 2011/4/19 アルゴリズムとデータ構造 5 3
Tree (木)構造
以下に示すようなデータ構造
循環構造を含まないことに注意
一般的には右下図の根付き木の
ことを木と呼ぶことが多い
root (根)
edge (辺)
node (節点)
rooted tree (根付き木)free tree (自由木)
4. 2011/4/19 アルゴリズムとデータ構造 5 4
Tree に関する用語
親( parent )
辺の上側(根に近い方)のノード
子( child )
辺の下側のノード
祖先( ancestor )
あるノードからみた親,親の親,親の親の親,・・・など
子孫( descendant )
あるノードからみた子,子の子,・・・など
葉( leaf )
子を持たないノード
内部ノード( internal node )
子を持つノード
深さ( depth )
根からあるノードに至るまでに通る辺の数
高さ( height )
根からもっとも遠いノードの深さ
5. 2011/4/19 アルゴリズムとデータ構造 5 5
確認問題
右の木について
ノード d の親は?
ノード d の子は?
ノード e の祖先は?
ノード b の子孫は?
葉を全て列挙せよ
ノード f の深さは?
高さは?
a
b c d
g he f
root (根)
li j k
6. 2011/4/19 アルゴリズムとデータ構造 5 6
実世界における木構造の例
会社の組織構造
生物の分類
問題:他にも木構造の例を挙げよ
社長
重役 重役
部長 部長 部長 部長 部長
課長 課長 課長
・・・
生物
植物界 動物界
無脊椎動物 脊椎動物・・・
7. 2011/4/19 アルゴリズムとデータ構造 5 7
木のバリエーション
順序木( ordered tree )
1つの頂点が複数の子を持つとき,これらの子の
順序に意味があるような木
例:人間の親族関係では,長男と次男の順序に意味があ
るから,順序木とみなせる
2分木( binary tree )
各節点の子の数がたかだか2であるような順序木
もっともよく使われる木
8. 2011/4/19 アルゴリズムとデータ構造 5 8
2分木の表現方法
2分木 T
根となるノードへのポインタ
を保持する root フィールド
を持つ
空の木は T.root = None とな
る
2 分木のノードは,要素を保
持するフィード elem に加え
て,左の子と右の子のそれぞ
れのノードを示す left と right
の2つのフィールドを持つ
子がいない場合, None とな
る
親ノードへのポインタを含め
る場合もある
T.root
left elem
right
9. 2011/4/19 アルゴリズムとデータ構造 5 9
一般の木の表現方法
各ノードは,子のリストの先頭を指すポインタと自
分が属するリストの次の要素を指すポインタを保持
するフィールドを持つ.
T.root
child sibling
10. 2011/4/19 アルゴリズムとデータ構造 5 10
木の走査( traversal )
行きがけ順走査( pre-order traversal )
親の節点を調べてから子供を順に調べていく
間順走査( in-order traversal )
最初の子を調べてから,親を調べ,その後で残り
の子を順に調べる
もっぱら2分木に対して使われる
帰りがけ順走査( post-order traversal )
子供を全部調べてから親を調べる
11. 2011/4/19 アルゴリズムとデータ構造 5 11
練習問題
右の二分木について
各要素( elem )の文字を
行きがけ順に表示
間順に表示
帰りがけ順に表示
した場合,それぞれどのよ
うな結果になるか?
T.root
left elem
a
right
b c
d e f
g h
12. 2011/4/19 アルゴリズムとデータ構造 5 12
2分木の走査
行きがけ順走査
再帰呼び出しを使う
def preorder(n):
if n != None:
# do_somthing(n.elem)
preorder(n.left)
preorder(n.right)
最初の呼び出しには木の根をパラメータとして渡す
>>> preorder(T.root)
15. 2011/4/19 アルゴリズムとデータ構造 5 15
2分木の走査(2)
間順走査
def inorder(n):
if n != None:
inorder (n.left)
# do_something(n.elem)
inorder(n.right)
帰りがけ順走査
def postorder (n):
if n != None:
postorder(n.left)
postorder(n.right)
# do_something (n.elem)
16. 2011/4/19 アルゴリズムとデータ構造 5 16
その他の手続き
ノードの深さを求める
# parent フィールド付きのノードの場合
def depth(n):
d = 0
while n.parent != None:
d = d + 1
n = n.parent
return d
木の高さを求める
def tree_height(n):
if n == None: return -1
return 1 + max(tree_height(n.left),
tree_height(n.right))
17. 2011/4/19 アルゴリズムとデータ構造 5 17
練習問題
parent フィールドなしの木ノード作成を以下のよう
に定義する
def tnode(x, l, r):
return record({‘elem’: x, ‘left’: l,
‘right’: r})
2分木は以下のように生成できる
root = tnode(1,tnode(2,tnode(3,None,None),
tnode(4,None,None)),
tnode(5,None,
tnode(6,None, None)))
上記によって生成される2分木を図示せよ
ノードの値を print するように preorder, inorder,
postorder をそれぞれ定義し,実際に確認せよ