アルゴリズムとデータ構造 -...

19
アルゴリズムとデータ構造 10 整列のアルゴリズム (2 ) アルゴリズムとデータ構造#10 1 小技 : 同じような絵が描いてある ページは、PCのキー操作で 次前次前次前と往復すると 変化した場所が分かりやすい 注意 : 分かり易いように動作説明を 何枚かのスライドに分けて 少しずつ書いています (枚数にビックリしないでね) 補足 資料)

Upload: others

Post on 13-Oct-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

アルゴリズムとデータ構造

第10回 整列のアルゴリズム (2)

アルゴリズムとデータ構造#101

小技:同じような絵が描いてあるページは、PCのキー操作で次前次前次前と往復すると変化した場所が分かりやすい

注意:分かり易いように動作説明を何枚かのスライドに分けて少しずつ書いています(枚数にビックリしないでね)

(補足資料)

Page 2: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

A[ i ] の

◼ 親 A[ ⌊( i-1)/2⌋ ]

◼ 左の子 A[ 2i + 1 ]

◼ 右の子 A[ 2i + 2 ]

ヒープ (heap)

◼ 任意の節点 u に対し、「u の親の要素≦ u の要素」 が成立

◼ 今回の「ヒープソート」 では、逆に 「親≧子」 とする

アルゴリズムとデータ構造#10 2

以前の復習

8

7 5

2 6 3 5

0 1 5

8 7 5 2 6 3 5 0 1 5

0 1 2 3 4 5 6 7 8 9

◼ ヒープは、配列で表せる

0

1 2

3 4 5 6

7 8 9

0 1 5

2 6 3 5

7 5

8

木の絵⇔配列素直に対応させられる

「親≧子」なら、ヒープの根 A[0] に最大値

Page 3: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

ヒープソート (heap sort) の概要

◼ 「親≧子」 ヒープ

◼ 最大値は何?

◼ A[0] を見るだけ

◼ 時間計算量 O(1)

◼ 最大値を削除したい

◼ 残りの要素が 「親 ≧ 子」 を満たすように、「ヒープの維持」をする必要がある

◼ 木(ヒープ)の深さに比例する … 時間計算量 O(log n)

◼ ヒープソート

◼ 「最大値を取り出して、ヒープの維持」 を n 回繰り返すと、値の大きい順に取り出せる … 時間計算量 O(n log n)

まずは、ブラックボックスと思って、概要を学習

アルゴリズムとデータ構造#10 3

「ヒープの維持」が分かれば、ヒープソートはマスターできます(詳細は、次のページ)

n は要素数

重要

Page 4: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

ヒープソート (heap sort) の概要

5

8

7 5

2 6 3 5

0 1

◼ 「親≧子」 ヒープを作り、最大値を1つずつ取り出して並べる

アルゴリズムとデータ構造#10 4

親≧子となるように、配列上でヒープを作る(詳細は後で)

重要

Page 5: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

ヒープソート (heap sort) の概要

5

7 5

2 6 3 5

0 1

5

8

7 5

2 6 3 5

0 1

◼ 「親≧子」 ヒープを作り、最大値を1つずつ取り出して並べる

5

7 5

2 6 3 5

0 15

8

7 5

2 6 3 5

0 1

最大値を覚える

最大値を削除

8

7 5

2 6 3 5

0 1 5

ヒープの維持(親≧子を維持するように交換)

根 A[0] が空っぽで困るので、無理やり最後の葉を根に持ってくる

5, 7, 5を見比べて5 と 7を交換

5 を無理に持たため、そこの親子関係がくずれている→ 親子関係を修復する

親≧子となるように、配列上でヒープを作る(詳細は後で)

重要

Page 6: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

7

5 5

2 6 3 5

0 1

7

1

6 5

2 5 3 5

0

ヒープソート (heap sort) の概要

5

7 5

2 6 3 5

0 1

5

8

7 5

2 6 3 5

0 1

◼ 「親≧子」 ヒープを作り、最大値を1つずつ取り出して並べる

5

7 5

2 6 3 5

0 15

8

7 5

2 6 3 5

0 1

最大値を覚える

最大値を削除

8

7 5

2 6 3 5

0 1 5

ヒープの維持(親≧子を維持するように交換)

根 A[0] が空っぽで困るので、無理やり最後の葉を根に持ってくる

5, 7, 5を見比べて5 と 7を交換

5, 2, 6を見比べて5 と 6 を交換

ヒープになった

親≧子となるように、配列上でヒープを作る(詳細は後で)

重要

Page 7: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

7

5 5

2 6 3 5

0 1

7

1

6 5

2 5 3 5

0

ヒープソート (heap sort) の概要

5

7 5

2 6 3 5

0 1

5

8

7 5

2 6 3 5

0 1

◼ 「親≧子」 ヒープを作り、最大値を1つずつ取り出して並べる

5

7 5

2 6 3 5

0 15

8

7 5

2 6 3 5

0 1

最大値を削除

8

7 5

2 6 3 5

0 1 5

ヒープの維持(親≧子を維持するように交換)

根 A[0] が空っぽで困るので、無理やり最後の葉を根に持ってくる

5, 7, 5を見比べて5 と 7を交換

5, 2, 6を見比べて5 と 6 を交換

ヒープになった

7 6 5 2 5 3 5 0 1 8

8 7 5 2 6 3 5 0 1 5親≧子となるように、配列上でヒープを作る(詳細は後で)

最大値を覚える

最大値の削除+ ヒープの維持

最初

ヒープ 覚えていた最大値を戻す

配列の動きを追うと

Page 8: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

ヒープソート (heap sort) の概要

5

8

7 5

2 6 3 5

0 1

◼ 「親≧子」 ヒープを作り、最大値を1つずつ取り出して並べる

7 6 5 2 5 3 5 0 1 8

8 7 5 2 6 3 5 0 1 5親≧子となるように、配列上でヒープを作る(詳細は後で)

最大値の削除+ ヒープの維持

最初

6 5 5 2 1 3 5 0 7 8

ヒープ 覚えていた最大値を戻す

最大値の削除+ ヒープの維持

アルゴリズムとデータ構造#10 8

配列の動きを追うと

Page 9: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

ヒープソート (heap sort) の概要

5

8

7 5

2 6 3 5

0 1

◼ 「親≧子」 ヒープを作り、最大値を1つずつ取り出して並べる

7 6 5 2 5 3 5 0 1 8

8 7 5 2 6 3 5 0 1 5親≧子となるように、配列上でヒープを作る(詳細は後で)

最大値の削除+ ヒープの維持

最初

6 5 5 2 1 3 5 0 7 8最大値の削除+ ヒープの維持

最大値の削除+ ヒープの維持 を繰り返す

0 1 2 3 5 5 5 6 7 8

値の大きい順に後ろから並ぶ (ソート完了)

アルゴリズムとデータ構造#10 9

配列の動きを追うと

Page 10: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

5 0 3 2 5 8 5 7 1 6

「親≧子」 ヒープを作り、最大値を1つずつ取り出して並べる

heapsort(A,n):

step 1: Aを逆順にヒープ化

step 2: i ← n-1

step 3: temp ← A[0]

step 4: DELETEMAX(A,i)を実行

step 5: A[i] ← temp

step 6: i ← i-1

step 7: i < 2 ならば停止。そうでなければ step 3 へ 8 7 5 2 6 3 5 0 1 5

Step 1: 逆順にヒープ化

ヒープソート (heap sort)

10

8

7 5

2 6 3 5

0 1 5

親≧子となるように配列上でヒープを作る(詳細は後で)

アルゴリズムとデータ構造#10

図解は、以前のページのを簡略化しただけ

Page 11: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

5 0 3 2 5 8 5 7 1 6heapsort(A,n):

step 1: Aを逆順にヒープ化

step 2: i ← n-1

step 3: temp ← A[0]

step 4: DELETEMAX(A,i)を実行

step 5: A[i] ← temp

step 6: i ← i-1

step 7: i < 2 ならば停止。そうでなければ step 3 へ 8 7 5 2 6 3 5 0 1 5

Step 1: 逆順にヒープ化

ヒープソート (heap sort)

11

8

7 5

2 6 3 5

0 1 5

A[0] がヒープの根 (最大値)

最大値を削除+ヒープの維持(詳細は後で)

8

7 5

2 6 3 5

0 1 5

7 6 5 2 5 3 5 0 1 8

7

5 5

2 6 3 5

0 1

7

6 5

2 5 3 5

0 1

最大値を削除

最下段最後の葉を根に移動

5

7 5

2 6 3 5

0 1

親≧子を維持するように交換

「親≧子」 ヒープを作り、最大値を1つずつ取り出して並べる

親≧子となるように配列上でヒープを作る(詳細は後で)

図解は、以前のページのを簡略化しただけ

Page 12: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

heapsort(A,n):

step 1: Aを逆順にヒープ化

step 2: i ← n-1

step 3: temp ← A[0]

step 4: DELETEMAX(A,i)を実行

step 5: A[i] ← temp

step 6: i ← i-1

step 7: i < 2 ならば停止。そうでなければ step 3 へ

8

7 5

2 6 3 5

0 1 5

7 6 5 2 5 3 5 0 1 8

7

5 5

2 6 3 5

0 1

7

6 5

2 5 3 5

0 1

1

6 5

2 5 3 5

0

6

0

5 5

2 1 3 5

6 5 5 2 1 3 5 0 7 8

0

5 5

2 1 3 5

5

2 5

0 1 3 5

5 2 5 0 1 3 5 6 7 8

ヒープソート (heap sort)

A[0] がヒープの根 (最大値)

最大値を削除+ヒープの維持(詳細は後で)

最大値を削除

最下段最後の葉を根に移動

5

7 5

2 6 3 5

0 1

「親≧子」 ヒープを作り、最大値を1つずつ取り出して並べる

親≧子となるように配列上でヒープを作る(詳細は後で)

Step 3~7を繰り返す

親≧子を維持するように交換

図解は、以前のページのを簡略化しただけ

Page 13: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

ヒープの維持 HEAPIFY(A,i,n)

アルゴリズムとデータ構造#10 13

節点 iに関してヒープの維持

ヒープの大きさは n

要素数が n の配列 A において、 A[2i+1] と A[2i+2] をそれぞれ根とする

2つのヒープを、A[i ]を根とするヒープに統合する

左部分木 右部分木

HEAPIFY(A,0,9) 実行例

Step 1:

そうでないなら j ← arg max {A[k ]: k∈{2 i +1, 2 i+2}, k < n }

Step 2: A[ i ] ≥ A[ j ] ならば停止.

そうでなければ A[ i ] と A[ j ] の中身の交換 (これを子で繰り返す)

A[ ] の値が大きい方の子を j

5

7 5

2 6 3 5

0 1

i

j

Step 1:

アイデア

Page 14: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

ヒープの維持 HEAPIFY(A,i,n)

14

節点 iに関してヒープの維持

ヒープの大きさは n

要素数が n の配列 A において、 A[2i+1] と A[2i+2] をそれぞれ根とする

2つのヒープを、A[i ]を根とするヒープに統合する

左部分木 右部分木

HEAPIFY(A,0,9) 実行例

Step 1: 2 i+1 > n-1 ならば停止.

そうでないなら j ← arg max {A[k ]: k∈{2 i +1, 2 i+2}, k < n }

Step 2: A[ i ] ≥ A[ j ] ならば停止.

そうでなければ A[ i ] と A[ j ] の中身の交換、i ← j として step 1 へ

A[ ] の値が大きい方の子を j配列の範囲外

5

7 5

2 6 3 5

0 1

5 7 5 2 6 3 5 0 1 5

0 1 2 3 4 5 6 7 8 9

i

j

・ もともと A は A[9] までの配列だった・今回は n = 9 (ヒープの大きさ 9)で呼ばれたので、それと関係なく A[0] ~ A[n-1] をヒープとして扱う

Page 15: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

7

5 5

2 6 3 5

0 1

7

1

6 5

2 5 3 5

0

5

7 5

2 6 3 5

0 1

ヒープの維持 HEAPIFY(A,i,n)節点 iに関してヒープの維持

ヒープの大きさは n

要素数が n の配列 A において、 A[2i+1] と A[2i+2] をそれぞれ根とする

2つのヒープを、A[i ]を根とするヒープに統合する

左部分木 右部分木

Step 1: 2 i+1 > n-1 ならば停止.

そうでないなら j ← arg max {A[k ]: k∈{2 i +1, 2 i+2}, k < n }

Step 2: A[ i ] ≥ A[ j ] ならば停止.

そうでなければ A[ i ] と A[ j ] の中身の交換、i ← j として step 1 へ

A[ ] の値が大きい方の子を j配列の範囲外

HEAPIFY(A,0,9) 実行例

5 7 5 2 6 3 5 0 1 5

0 1 2 3 4 5 6 7 8 9

7 5 5 2 6 3 5 0 1 5

0 1 2 3 4 5 6 7 8 9

7 6 5 2 5 3 5 0 1 5

0 1 2 3 4 5 6 7 8 9

i

j i

j i

Page 16: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

逆順ヒープの最大値を削除 (A[tail] の要素を根に)

+ ヒープの維持

step 1: A[0] ← A[tail]

step 2: HEAPIFY(A,0,tail) を実行

サブルーチン DELETEMAX(A,tail)

16アルゴリズムとデータ構造#10

ヒープは最初 A[0] ~ A[tail]に入っている

ヒープは A[0] ~ A[tail - 1] に入っている (Aの大きさは tail)

8

7 5

2 6 3 5

0 1

8 7 5 2 6 3 5 0 1 5

0 1 2 3 4 5 6 7 8 9

5

heapsort(A,10) を実行すると、最初の DELETEMAX( ) は、DELETEMAX(A, 9) で実行

Page 17: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

逆順ヒープの最大値を削除 (A[tail] の要素を根に)

+ ヒープの維持

step 1: A[0] ← A[tail]

step 2: HEAPIFY(A,0,tail) を実行

Step 2HEAPIFY(A,0,9)

サブルーチン DELETEMAX(A,tail) ヒープは最初 A[0] ~ A[tail]に入っている

heapsort(A,10) を実行すると、最初の DELETEMAX( ) は、DELETEMAX(A, 9) で実行

5

7 5

2 6 3 5

0 1

7

1

6 5

2 5 3 5

0

8

7 5

2 6 3 5

0 1

8 7 5 2 6 3 5 0 1 5

0 1 2 3 4 5 6 7 8 9

5 7 5 2 6 3 5 0 1 5

0 1 2 3 4 5 6 7 8 9

7 6 5 2 5 3 5 0 1 5

0 1 2 3 4 5 6 7 8 9

5

Step 1A[0] ← A[9]

ヒープは A[0] ~ A[8] 後で、A[9] ← temp (もとの最大値)を実行する

ヒープは A[0] ~ A[tail - 1] に入っている (Aの大きさは tail)

Page 18: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

ヒープ構築の概要

◼ HEAPIFY(A, i, n) を実行すると、

節点 i と、その左部分木のヒープ、右部分木のヒープが

1 つのヒープになる (既に学習済み)

◼ 葉は、大きさ 1 のヒープ

◼ 葉以外の節点は、葉の側から根の側へ、ヒープにしていけばよい

5

0 3

2 5 8 5

7 16

5 0 3 2 5 8 5 7 1 6

i = ⌊(n-2)/2⌋, ⌊(n-2)/2⌋–1, …, 1, 0 の節点 i

最後の葉 A[n – 1] の親

HEAPIFY(A, i, n)

Page 19: アルゴリズムとデータ構造 - 北海道大学arim/pub/algo/algo10_addon.pdfアルゴリズムとデータ構造 第10回整列のアルゴリズム(2) 1 アルゴリズムとデータ構造#10

5

0 3

2 5 8 5

7 16

5 0 3 2 5 8 5 7 1 6

5

0 3

2 6 8 5

7 1 5

5 0 3 2 6 8 5 7 1 5

5

0 3

7 6 8 5

2 1 5

5 0 3 7 6 8 5 2 1 5

5

0 8

7 6 3 5

2 1 5

5 0 8 7 6 3 5 2 1 5 5 7 8 2 6 3 5 0 1 5

5

7 8

2 6 3

0 1 5

5

8 7 5 2 6 3 5 0 1 5

8

7 5

2 6 3

01 5

5

ヒープ構築アルゴリズム

19

HEAPIFY(A,4,10) HEAPIFY(A,3,10) HEAPIFY(A,2,10)

HEAPIFY(A,1,10) HEAPIFY(A,0,10)

Step 1. For i = ⌊(n-2)/2⌋, …, 0 HEAPIFY(A, i, n)

最後の葉 A[n – 1] の親 根