アルゴリズムとデータ構造 第3章 ヒープ 5月31日分の復習 情報知能学科 白井英俊 二進木(二分木)とは 高々2個 • Binary tree の訳語 定義: どの頂点も2個以下の子をもつ木 2個の子は左の子と右の子のどちらか 左 右 0個の子 1個の子 2個の子 左 右 頂点の深さと木の高さ • 根と頂点の間の枝の数が「頂点の深さ」 • 最も深い頂点の「深さ」が「木の高さ」 根=深さ 0 深さ 1 深さ 2 深さ 3 深さ 4 この木の 高さ= 4 練習問題 この木の高さは? 左部分木の高さ と 右部分木の高さ の大きい方+1 3 1 8 5 10 7 9 12 二進木を用いたソート(sort) 二進木を利用して、n個の実数を小さいものから 大きいものへと昇順に並べる(ソート, sort)こ とを考えよう このために用いる二進木を「二分探索木」 (binary search tree)と呼ぶ 与えられた実数を1個ずつ読み込み、それぞれを 頂点に格納しながら、二分探索木を作っていく すべての実数に対応する頂点をもつ二分探索木 の完成後、すべての頂点を中間順で読みだす。 これによりソートが完成される 二進木のデータ構造 • 二進木の場合、子は左か右しかない だから、「一般の木」よりも特殊なデータ構造を 考えるのが便利 「引数=値」とは、引数が省略できること、省略 された場合に「値」となることを意味する class Vertex def initialize(data=“ “, left=nil, right=nil) @data = data @left = left @right = right end # initialize attr_attribute :data, :left, :right end # class 木に要素xを加えるインスタンスメソッド insert(x) class Vertex def initialize(data=“ “, left=nil, right=nil) @data = data @left = left @right = right end # initialize に続けて… def insert(x) # xは付け加える要素 1)xがdata より小さいなら if x < @data a) 左の子がなければ if (@left == nil) xの値をもつ新たな頂点 @left = Vertex.new(x) を作成し左の子とする else b) さもなくば @left.insert(x) end 2) 1)でなければ 右の子に対して同様にする else … インスタンスメソッドinsert(x) 続き def insert(x) if (x < @data) # x がtの値より小さい場合 if (@left = = nil) # t の左の子がないなら @left = Vertex.new(x) # xを値とする頂点を 左 else # 作って t の左の子に left @left.insert(x) # 左の子に対し再帰 end #if # xがtの値以上の場合 elsif (@right = = nil) # t の右の子がないなら @right = Vertex.new(x) # xを値とする頂点を 右 # 作って t の右の子に right else @right.insert(x) # 右の子に対し再帰 end # if end # def 二分探索木を作る…(続き) 2<4だから 3<4だから 左 左 2<3だから 左 2 1 3 4<10から 4<5だから 4<8だから 4<6だから 右 右右 右 4 5 6<8だから 左 入力データ: {4 5 8 3 6 5<8だから 5<10から 5<6だから 右 右 10 2 9 1 } 右 8 6 8<10から 右 10 9 どこにノードができるか予 想しよう 「木のなぞり」、または値の読出し 頂点の値が真ん中の位置で読 み出されるので「中間」順 • 中間順の読出し 左の子、根頂点の値、右の子 という順に、値を読み出す ・参考:先行順、後行順、もある 例 スタートはいつ 根頂点(2) 8 も根が基準 左(1) 5 だから、 5, 8, 10 10 右(3) 中間順の「木のなぞり」 根頂点(2) 8 左(1) 5 3 10 7 スタートはいつ も根が基準 右(3) 20 「左部分木」は(部分)木なので、 中間順が適用され: 根の「右部分木」は (部分)木なので、中間 順が適用され: 他の「木のなぞり」 • 先行順: 「根頂点の値」、左の子、右の子 • 後行順: 左の子、右の子、 「根頂点の値」 先の演習問題の木に対し、先行順と後行順の それぞれで「木をなぞる」と、どのようになる か? 先行順の「木のなぞり」 根頂点(1) 8 左(2) 5 3 10 7 スタートはいつ も根が基準 右(3) 根の「右部分木」は 20 (部分)木なので、 先行順が適用され: 「左部分木」は(部分)木なので、 先行順が適用され: 後行順の「木のなぞり」 根頂点(3) 8 左(1) 5 3 10 7 スタートはいつ も根が基準 右(2) 根の「右部分木」は 20 「左部分木」は(部分)木なので、 後行順が適用され: (部分)木なので、 後行順が適用され: 応用問題:数式の木 例: (a+b)*(c-d*e) は次の二進木で表現される(葉に は変数が、葉以外の頂点は演算子が書かれる) * + a ー b * c d e 数式の木の問題 • 先の木をそれぞれ次でなぞった時 1) 中間順(inorder) a+b*c–d*e 2) 先行順(preorder) ポーランド記法 * + a b – c * d e 3) 後行順(postorder) 逆ポーランド記法 ab+cde*–* 逆ポーランド記法は「日本語的」
© Copyright 2024 ExpyDoc