SKIRTING AND WALL COVERING...WALL COVERING 巾木・立面仕上げ材 ソフト巾木・ロング巾木・ササラ巾木 450 ソフト巾木(木目)・ロング巾木(木目)
アルゴリズム及び実習④ - math.ryukoku.ac.jpqma/education/algo/... ·...
Transcript of アルゴリズム及び実習④ - math.ryukoku.ac.jpqma/education/algo/... ·...
1
アルゴリズム及び実習④
馬 青
2
木
• 木は、分岐関係、階層関係のようなデータ間の関係を表現するデータ構造の一種である。
3
木の用語
A
B C
D E F G
H I
節点(node)
枝(branch)辺(edge)
根(root)
葉(leaf)
親(parent)
子(child)
兄弟(sibling)
ラベル(label)
部分木
レベル0
レベル1
レベル2
4
2分木、完全2分木
• どの節点も子節点の数が2つ以下で構成されている木を2分木という。
• 一番下のレベルを除くすべてのレベルに節点が詰まっていて一番下のレベルでは左から順に節点が詰まっている2分木を完全2分木という。
B
A
D E
C
F
完全2分木
5
• 2分木の各節点に番号を付与することで、配列で表現できる。
• 上記の木の場合:a[0]=‘A’, …, a[5]=‘F’
B
A
D E
C
F
2分木と配列(1/2)(0)
(1) (2)
(4)(3) (5)
6
2分木と配列(2/2)親子節点の番号間の関係
当然、逆、つまり、配列(例:a[0],...,a[6]=11 15 13 30 1925 17)を二分木で表現できる。
11(0)15(1) 13(2)
30(3) 19(4) 25(5) 17(6)
(k)
(2k+1) (2k+2)0から数える場合
7
演習問題
1.配列(10, 30, 20, 40, 60, 50)を2分木に直しなさい。
2.以下の2分木を配列に直しなさい。
30
10 20
15 40 45 60
100 200
8
ヒープ木とヒープソート
ヒープ木は、親節点のデータがそのどの子節点のデータよりも小さいか等しいという条件(または逆に大きいか等しいという条件)が満たされる完全2分木である。
• ヒープ木はヒープともいう。
ヒープソートは、配列を2分木とみなし、ヒープ木の性質を利用した効率的なソート法である。つまり
• 根節点のデータは必ず最小(または最大)なので、それを順次に取り出したらよい。
9
Question
ヒープ木かどうか判断しなさい。
100
30 20
10 5 15 8
10
40 20
30 60 50
10
ヒープソートの大まかな説明
ヒープ木
(最小)
(最小)
(最小)
ヒープ木(黒)非ヒープ木
(最小)
(次に最小)
非ヒープ木 ヒープ木(黒)
(最小)
(3番目最小)
非ヒープ木
小大
大
配列に直すと、データは降順配置になっている
データ交換 ヒープ化
データ交換 ヒープ化
データ交換
以上の操作を繰り返す
全体のヒープ化
11
ヒープソートの主な処理
• 全体のヒープ化
• データ交換
• ヒープ化
基本:(大きいデータを)「下方に落とす」処理
繰り返し
12
データを下方に落とす:DownHeapDownHeap(1,21)の場合適用条件:節点(1)とその子節点がヒープ条件を破っていて、節点1以降21まですべての節点はヒープ条件を保っている。適用範囲:節点1~節点21
5
6 4
8 10
(1)
3
(8)
6
(17)79
(3)3
6 4
8 10
(1)
5
(8)
6
(17)79
(3)3
6 5
8 10
(1)
4
(8)
6
(17)79
(3)
節点(8)と(17)を比較し、ヒープ条件を満たしているので、DownHeap操作が終了
ケース1
13
15
6 4
8 10
(1)
3
(8)
6
(17)79
(3)3
6 4
8 10
(1)
15
(8)
6
(17)79
(3)
節点(17)の子節点が(35)で22を超えたので、DownHeap操作が終了
ケース2
3
6 15
8 10
(1)
4
(8)
6
(17)79
(3)
3
6 7
8 10
(1)
4
(8)
6
(17)159
(3)
データを下方に落とす:DownHeap
14
Question以下の2分木に対し、DownHeap(0,3)を適用すると、ど
のような木が得られるか。
100
5 8
10 3 2 1
15
DownHeapの手順DownHeap(f,t)の場合:
• 初期設定:節点fを親節点とする。
• 子節点同士を比較し、小さい方を選ぶ。
• 選んだ子節点と親節点を比較し、親節点の方が大きければ親と子を交換し、今の子節点を親節点とする。そうでなければ処理終了。
• 子節点同士を比較し、小さい方を選ぶ。
• 選んだ子節点と親節点を比較し、親節点の方が大きければ親と子を交換し、今の子節点を親節点とする。そうでなければ処理終了。
• 終了:子節点の番号がtを超えれば、処理終了
16
演習問題
次のDownHeap(f,t)アルゴリズムを完成させなさい。
17
DownHeap(f,t)のアルゴリズム(1/2)
入力: 部分配列a[f],...,a[t]{ただし:a[f+1]...a[t]はすでにヒープの条件を満たしている。}
出力: ヒープ条件を満足する部分配列a[f]...a[t]補助: i: 親節点番号、j: 子節点番号
18
1.{初期設定: i:親節点、j:左の子節点}i=?, j=?とおく
2. 条件j≦tが満たされる間、次の操作を繰り返す
2.1 {左右に子があり、かつ右の子が小さければ}
j+1≦tかつ?であれば
{右の子を選択}j=?とおく
2.2 {親と子がヒープ条件を破っていれば}
?であれば
{親と子のデータを交換し、子を親とし、子の子を子とする}
?と?を交換、i=?, j=?とおく。
そうでなければ繰り返す操作を抜け出す
DownHeap(f,t)のアルゴリズム(2/2)
19
j+1≦tについての補足説明(1/2)ヒープ木は完全2分木なので
最後の親節点以外は必ず左右の子節点を持つ
30
15 25
11 19 13 17
30
15 25
11 19 13
30
15 25
11 19
30
15 25
11 13
最後の親節点
○ ○
○ ×
① ②
③ ④
j+1>t
• たとえばDownheap(0,3)を適用としたとき
100
5 8
10 3 2 1
5
10 8
100 3 2 1
j=3のとき、j+1>tなので左右比較はしないで親子の交換を行う
j+1≦tについての補足説明(2/2)
21
21
終了条件j ≦ tの使用例
• j ≦ t について Downheap(0,2)を適用としたとき
100
8 5
4 3 2 1
5
8 100
4 3 2 1
j=2になったとき、これ以上親子の比較・交換はしない。
22
ヒープソートの主な処理
• 全体のヒープ化
• データ交換
• ヒープ化
基本:「データを下方に落とす」処理
繰り返し
再掲
23
全体のヒープ化
考え方:
葉節点を除き、最下段で最右端の節点から左の節点へ、そして上のレベルの節点へと、DownHeap処理を順次適用していくことによって
データ全体をヒープ化することができる。
24
30(0)
15(1) 13(2)
19(3) 11(4) 25(5) 17(6)
全体のヒープ化の例(1/2)30(0)
15(1) 25(2)
19(3) 11(4) 13(5) 17(6)
a
b
c
30(0)
11(1) 13(2)
19(3) 15(4) 25(5) 17(6)
DownHeap(2,6)
DownHeap(1,6)
DownHeap(0,6)その1
25
全体のヒープ化の例(2/2)
d
e
11(0)
30(1) 13(2)
19(3) 15(4) 25(5) 17(6)
11(0)
15(1) 13(2)
19(3) 30(4) 25(5) 17(6)
DownHeap(0,6)その2
結果
26
Question
DownHeap処理を上の節点から下の節点へと適用してもOKか?理由は?
27
Question• 以下の2分木を(親≦子のような)ヒープ木に直しなさい。
100
30 20
10 5 15 8
28
配列a[0],...,a[n-1]の場合
• 初期設定:最下段最右端の親節点の番号を変数mに与える
• DownHeap(m,n-1)を実行する
• DownHeap(m-1,n-1)を実行する
• DownHeap(0,n-1)を実行する
全体ヒープ化の手順
29
30
15 25
11 19 13 17
30
15 25
11 19 13
30
15 25
11 19
① ②
③
最下段最右端の親節点とは
30
15 25
11 ④
30
演習問題
次の全体のヒープ化のアルゴリズムを完成させなさい。
31
入力: ヒープ条件を満足しない配列a[0],...,a[n-1]出力: ヒープ条件を満足する配列a[0],...,a[n-1]補助: i:節点番号(配列の要素番号)、m:親節点番号(親節点に対応する配列の要素番号)
1.{初期設定}m=[?]とおく。[x]はxを超えない最大の整数である。前々ページの例①②ではm=2
2. i=?から?について、DownHeap(?, ?)を実行する
MakeHeapアルゴリズム
32
ヒープソート
考え方:
ヒープ木はその根節点にあるデータは必ず最小なものなので、それを取り出しては次に最小のものを根節点に持っていくことを繰り返すと、小さいデータから大きいデータまでを順次に取り出すことができる。
33
ヒープソートの大まかな説明
ヒープ木
(最小)
(最小)
(最小)
ヒープ木(黒)非ヒープ木
(最小)
(次に最小)
非ヒープ木 ヒープ木(黒)
(最小)
(3番目最小)
非ヒープ木
小大
大配列に直すと、データは降順配置になっている
データ交換 ヒープ化
データ交換 ヒープ化
データ交換
以上の操作を繰り返す
全体のヒープ化
再掲
34
Question
• 「全体のヒープ化」と「ヒープ化」はどう違う?
35
ソート例(1/3)
P29(プリントではP25)の(e)を配列にすると、以下になる
要素番号 0 1 2 3 4 5 6配列の値 11 15 13 19 30 25 17これは以下のようにソートできる。
まず、2分木の根にあるデータと最下段最右端の葉にあるデータを入れ替えると、下の結果を得る
要素番号 0 1 2 3 4 5 6配列の値 17 15 13 19 30 25 11
全体がヒープ化されていることに注意!!
36
ソート例(2/3)次にヒープ条件を満たすよう、データ17を「下方に落とす」(DownHeap(0,5)を実行する)と下の結果を得る
要素番号 0 1 2 3 4 5 6配列の値 13 15 17 19 30 25 11(注意:「下方に落とす」操作は末尾の11を除いて行う)
次に、2分木の根にあるデータと最下段2番目に最右端の葉にあるデータを入れ替え、下の結果を得る
要素番号 0 1 2 3 4 5 6配列の値 25 15 17 19 30 13 11
37
次にヒープ条件を満たすようにデータ25を「下方に落とす」。
以上の操作を繰り返すことによって、最終的に以下のような降順ソーティング結果が得られる
要素番号 0 1 2 3 4 5 6配列の値 30 25 19 17 15 13 11
ソート例(3/3)
38
演習問題
ヒープソート法で以下の配列をソートする全過程(次のページ参照)を書きなさい。
(10, 30, 20, 40, 60, 50)
すでに全体がヒープ化されていることに注意!!
39
ソートの全過程(10, 30, 20, 40, 60, 50)(?, ?, ?, ?, ?, ?) ←交換(?, ?, ?, ?, ?, ?) ←DownHeap(?, ?, ?, ?, ?, ?) ←交換(?, ?, ?, ?, ?, ?) ←DownHeap(?, ?, ?, ?, ?, ?) ←DownHeap(?, ?, ?, ?, ?, ?) ←交換(?, ?, ?, ?, ?, ?) ←DownHeap(?, ?, ?, ?, ?, ?) ←交換(?, ?, ?, ?, ?, ?) ←DownHeap(?, ?, ?, ?, ?, ?) ←交換(60, 50, 40, 30, 20, 10) ←DownHeap
40
ヒープソートの手順
• 配列a[0],…,a[n-1]に対し、MakeHeapで全体をヒープ化
• a[0]とa[n-1]を交換する
• DownHeap(0,n-2)を実行する
• a[0]とa[n-2]を交換する
• DownHeap(0,n-3)を実行する
• a[0]とa[1]を交換する
• DownHeap(0,0)を実行する
41
演習問題
次のヒープソートアルゴリズムを完成させなさい。
ヒント:アルゴリズム(関数)DownHeapとMakeHeapはこのまま使える。
42
HeapSortアルゴリズム
入力: ソートされていない配列a[0],...,a[n-1]出力: ソートされた配列a[0],...,a[n-1]補助: i: 配列の要素番号(節点番号)
1.{全体のヒープ化}?をa[0],...,[n-1]に適用
2. i=?から?について、次の操作を繰り返す
2.1 ?と?を入れ替える
2.2 ?を実行する
43
Question
昇順にソートしたい場合、どうすればよいでしょうか?
44
計算量• DownHeap(f,t)において、処理回数(=繰り返しの回数=比較・交換の回数)をpとすると、繰り返し変数jは2f, 22f, ... , 2pfのように変化していくので、t=2pfが成立し、 最大処理回数
p=log2(t/f)≒log2(n)• MakeHeapにおいて、(m+1)回のDownHeapを行うので、最大処理回数
(m+1)p=(m+1)log2n=(n/2)log2n• HeapSortは1回のMakeHeap+(n-1)回の交換+(n-
1)回のDownHeapで構成されるので、最悪の計算量のオーダーでもO(nlog2n)である。
45
第4回実習課題(1/2)1.データを下方に落とすアルゴリズムを実現する関数void
DownHeap(int a[], int f, int t)を作成し、その動作を確認できるプログラム(ex04-downheap.c)を作成しなさい。
2.データ全体のヒープ化アルゴリズムを実現する関数void MakeHeap(int n, int a[])を作成し、その動作を確認できるプログラム(ex04-makeheap.c)を作成しなさい。ただし、nはデータの個数、a[]はデータ配列である。
46
第4回実習課題(2/2)3.課題1で作成した関数を利用し、ヒープ条件を満たす任
意の配列a[0],…,a[n-1]と任意の要素番号no(ただし、no>0)が与えられたとき、a[no]とa[0]の値を交換し、a[0],…,a[no-1]をヒープ化するプログラム(ex04-swap-downheap.c)を作成しなさい。
4.課題2と課題3で作成したプログラムを参考に、ヒープソートアルゴリズムを実行する関数void HeapSort(int n, int a[])を作成し、その動作を確認できるプログラム(ex04-hsort.c)を作成しなさい。ただし、nはデータの個数、a[]はデータ配列である。上記完成後、昇順プログラムに直しなさい。
47
課題1の実行例./a.outInput the data (end with Ctrl-D)30 15 25 19 11 13 17 (Ctrl-D)Input f and t 0 6Result 15 11 25 19 30 13 17 ./a.outInput the data (end with Ctrl-D) 30 15 25 19 11 13 17 (Ctrl-D)Input f and t 1 5Result 30 11 25 19 15 13 17
注意:ここではDownHeapの動作を確認するためだけなので、任意の入力データをOKとする。つまり、入力データにDownHeapの適用条件を考えていない。
48
課題2の実行例
./a.outInput the data (end with Ctrl-D)30 15 25 19 11 13 17(Ctrl-D) Result 11 15 13 19 30 25 17 ./a.outInput the data (end with Ctrl-D)5 4 3 2 1(Ctrl-D) Result 1 2 3 5 4
49
課題3の実行例./a.outInput the data (end with Ctrl-D)11 15 13 19 30 25 17(Ctrl-D)Input no4Result13 15 30 19 11 25 17./a.outInput the data (end with Ctrl-D)11 13 15 30 19 25 17(Ctrl-D)
Input no5Result13 19 15 30 25 11 17
50
課題4の実行例
./a.outInput the data (end with Ctrl-D)30 15 25 19 11 13 17 (Ctrl-D)Sorted data 30 25 19 17 15 13 11 ./a.outInput the data (end with Ctrl-D)1 2 3 4 5(Ctrl-D) Sorted data 5 4 3 2 1 ← ここでは降順のみ