アルゴリズムとデータ構造 第3章 ヒープ 6月7日分 情報知能学科 白井英俊 いろいろな木 • 木はグラフの特殊なもので、二進木は木の特殊なも のである。つまり、これらには「上位・下位」(含む、 含まれる)という関係がある。 • 講義で取り扱ういろいろな木の関係を図で表す データ構造 グラフ Nodeクラス 木 Vertexクラス 二進木 強平衡二進木 ヒープ 配列 強平衡二進木 差が0か1 • 教科書 p.27 強平衡二進木:すべての不完全頂点の深さ は「高々1しか違わない」ような二進木 • 用語(二進木において) 完全頂点:子の数が2の頂点 不完全頂点:子の数が0か1の頂点 強平衡二進木の練習 以下のうち、強平衡二進木はどれか? (1) (2) (3) (4) 強平衡二進木(続き) 完全頂点 不完全頂点 (2) (3) 深さ0 深さ1 深さ2 不完全頂点の差は高々1 不完全頂点の差は最大2 練習問題 前回調べた、高さ2の二進木において、 強平衡二進木はどれか? 予習問題:ヒープの条件(i)を満たすものは どれか? 高さ 2 の二進木 (1) (2) (3) (8) (7) (10) (11) (4) (5) (6) (9) (12) 高さ 2 の二進木(続き) (13) (16) (19) (14) (17) (20) (15) (18) (21) ヒープ • ヒープ(heap)とは、特殊な二進木 定義3.2 高さkの二進木Tがヒープであるための 必要十分条件は次の(i), (ii)を満たすこと (i) 深さ0 ~ k-1 の可能な頂点はすべて使われ、 深さkの頂点は左から順に使われている (ii) 頂点uが頂点vの親なら uの値( f(u) ) ≧ vの値( f(v) ) 親 子 「可能な頂点」と「使われている」 高さ 1 の二進木を考える ① 「可能な頂点」は3個 ② ③ (1) 実際に木の 頂点になっ ている ② ① 木の頂点になりうるもの (2) ① ③ ①と②が使われ③ は使われていない ①と③が使われ② は使われていない ヒープ(続き) • ヒープの条件の(i)は「強平衡二進木」の条 件よりもキツイ • 木Tがヒープならば、Tは強平衡二進木で もある ヒープ(続き) • 高さ2の二進木のいくつか:ヒープの条件(i)を満たすの はどれか? 深さ0,1の頂点はすべて使われ、 深さ2の頂点は左から使われている 演習問題 • 高さ2のヒープ条件(i)を満たす二進木をすべ て書き下す (ヒント: 4通りある) 高さ 2 の二進木 (1) (2) (3) (8) (7) (10) (11) (4) (5) (6) (9) (12) 高さ 2 の二進木(続き) (13) (16) (19) (14) (17) (20) (15) (18) (21) ヒープ(続き) • ヒープの条件(ii) 共にヒープ条件(i) は満たしている 8 5 3 8 7 5 7 10 5 ≧ 10 が不成立! ヒープの条件(ii): 親の頂点の値 ≧ 子の頂点の値 ヒープの作成 • 二分探索木を作ってソートするのではな く、ヒープを作ってソートするメリット 頂点数(=入力データ数)をnとすると、 木の高さは常に O(log n) ⇒ 二分探索木を使った場合の最悪のケー スが起こらない 最悪のケース: 葉以外のどの頂点も 配列を使ってヒープを表現可能 子が1つしかないような 場合。二分探索が使え (教科書p.31-32) ず、木の高さもO(n)にな る。 配列を用いたヒープの表現 ① ⑤ ⑥ ⑧ ⑨ 根 { ② ④ 0 1 2 深さ1 3 ③ 4 深さ2 5 ⑦ 6 7 深さ3 8 9 偶数: 左の子 奇数: 右の子 … … 二進木による表現 { { 根以外は 注目:深さkの一番左の子の番号は 2k 配列による表現 それでは一番右の子の番号は ? ヒープの特徴 頂点の番号のつけ方: 1 二進木 上から下、左から右 3 2 4 8 5 9 6 7 10 この番号の付け方から、高さ n (> k)のヒープでは、 ★深さ k の最も左の頂点の番号は 2k ★深さ k の最も右の頂点の番号は 2(k+1) - 1 ヒープの演習 1. ヒープの条件(i)を持つ 高さ2、頂点数6の二進木 を書け 2. ヒープの条件(i)を持つ 高さ3、頂点数 11 の二進木 を書け 定義3.2 高さkの二進木Tにおいて (i) 深さ0 ~ k-1 の可能な頂点はすべて使われ、 深さkの頂点は左から順に使われている ヒープの演習(続) 3. 右の配列に対 応する二進木を 書け。 ただし、ヒープを 配列で表す規則 に従うとする。 これはヒープの 条件を満たして いるか? 0 1 2 3 4 5 6 7 8 9 10 11 30 25 28 20 24 26 18 19 11 ヒープの演習(続) 4. 以下の二進木に対応する配列をかけ。ただ し、ヒープを配列で表す規則に従うとする。こ れはヒープの条件をすべて満たすか? 20 15 10 4 1 11 7 3 5 2 6 ヒープへの要素の追加(挿入)手続き 手続き:以下の2ステップで行う • 新たな要素を値とする頂点をヒープに追加 ⇒ 条件(i)を満たすところに (2) 次に、ヒープ条件(ii)を満たすように修 正する 定義3.2 二進木Tにおいて (ii) 頂点uが頂点vの親なら uの値≧ vの値 ヒープへの要素の追加(1) 例: 定義3.2 二進木Tにおいて (ii) 頂点uが頂点vの親なら uの値≧ vの値 8 5 3 7 10 に3を追加する… それには、ここしかない そして、ヒープ条件(ii)を満たし ているのでヒープが完成 さらに、 10を追加する。。。 これは、ヒープ条件(ii)を満たして いないので『修正』が必要 ヒープへの要素の追加(1)続き ヒープの条件(i)を満たすように要素を追加する ことは、 (b)二進木で表す場合、「可能な頂点を左から順 に使う」 (a) 配列で表す場合は分かりやすい ⇒ ヒープの最後の要素のインデックスを x とすれば、x+1 番目に要素を追加すれ ばよい ヒープへの要素の追加(2)「修正」 • 追加した頂点を v とする • ヒープの条件(ii)は、 親頂点の値≧子頂点の値 だから、これが満たされていればOK. そうでなければ、上の条件を満たすように、頂 点を入れ替えていく(修正する) ヒープへの要素の追加(2)続き ヒープへの要素の追加の完成 条件を破ってい る 8 5 3 7 10 条件を破ってい る 具体的に例を用いてヒープを作る 入力データ: 8 5 3 1 7 10 20 { 8 5 7 3 10 9 6 1 20 } 9 6 ヒープ条件(ii)を破っ ているので、『修正』 が必要 問題: ヒープ条件(ii)が成り立つ ようにするには、どのように『修 正』したらよいか? ヒープの演習(続) 5 (a) 問題(4)において、10番目の要素として 「15」が入っているとする。1~10番目までの要 素からなる配列は、ヒープの条件を満たしてい るか?その理由も述べよ。 (b)問題(4)において、10番目の要素として「40」 が入っているとする。1~10番目までの要素から なる配列は、ヒープの条件を満たしているか? その理由も述べよ。 (b) (5a), (5b)で、「ヒープになっていないも の」に対し、1~10番目までの要素からなる配列 をヒープにする(演習3.6)ことを考える。その 結果のヒープを示せ。 ヒープの演習(続) 6. 以下の配列はヒープの条件を満たしているか?満たしていなけれ ば(i)を行え。 (i) 1番目の要素から順に10番目までの要素をヒープにする操作を 行い、最終的に得られたヒープを示せ。 (ii) 次に、1番目の要素と10番目の要素を入れ替え、1~9番目の要 素からなる配列をヒープに修復せよ(演習3.7) (iii) これに続けて9,8,…,2と順に一番目の要素と入れ替えてはヒープ に修復する操作を行い、最終的に得られた配列を示せ。 (iv) n 個の要素を持つ配列(1~n番目に要素があるとする)に対し、 (i)の操作でヒープを作る計算量のオーダーはどのくらいか、また (ii)の手順で最終の配列を得るための計算量のオーダーはどのく らいか? 1 2 30 25 3 4 5 6 20 16 24 18 7 8 9 12 10 8 10 15 ヒープソート(Heap Sort) ヒープを用いてソート(並び替え)を行う 手続き: (1) x1, x2, …, xn からヒープ(木)を作る 計算量は O(n * log n) ヒープ木においては根が最大の値の頂点 (2) 根と『最も深い頂点のうち最も右端の頂点』とを交 換し、『根だった頂点をヒープから切り離し』てから ヒープを作り直す。この操作一回ごとの計算量は O(log n) (3) (2)を繰り返し、切り離された頂点をすべて並べると ソート完成(新しく切り離された頂点が最小、古いも のが最大) ヒープソート(続き) ヒープの作り直し(ヒープソートのステップ(2)) 20 10 5 ≦ 8 1 3 ≧ 9 7 1. 根と『最も深く右側の頂 点』とを交換し、根だった頂 点を切り離す 2. ヒープ条件(ii)を満たすよ う、ヒープを作り直す 親頂点と、子頂点のう ち大きいほうを交換。 6 問題: ヒープをどのように作り直すか? 問題: この後ヒープをどのように作り直すか? ヒープソートの真髄 ヒープを配列で表わす ⇒『木』よりも簡単なデータ構造で実行可能 インデックスによって、根の頂点を簡単に求めること ができる また、注目している頂点のインデックスから、その親 や子の頂点が何かが簡単に計算できる 問題: 注目している頂点のインデックスをxとすると、 その親と子の頂点のインデックスは? 演習問題 配列を用いてヒープソートするプログラムを作る。 (1) 入力データからヒープ(配列で表現)を作る関数 (makeHeap)を作れ (2) ヒープにおいて、根と最後の要素とを交換する コード(swapNodes)を書け (3) 最後の要素のインデックスを x とすると、 1~(x-1) までの要素をヒープに作り直すコード (remakeHeap)を書け (4) 以上を組み合わせて、ヒープソートを行う関数 (heapSort)を書け
© Copyright 2024 ExpyDoc