PowerPoint Presentation

Similar documents
PowerPoint Presentation

memo

Microsoft PowerPoint - DA1_2018.pptx

Microsoft PowerPoint - DA1_2018.pptx

INTRODUCTION TO ALGORITHMS

Microsoft PowerPoint - DA1_2019.pptx

プログラム言語及び演習Ⅲ

memo

Microsoft PowerPoint - 06.pptx

memo

始めに, 最下位共通先祖を求めるための関数 LcaDFS( int v ) の処理を記述する. この関数は値を返さない再帰的な void 関数で, 点 v を根とする木 T の部分木を深さ優先探索する. 整数の引数 v は, 木 T の点を示す点番号で, 配列 NodeSpace[ ] へのカーソル

論理と計算(2)

Taro-再帰関数Ⅲ(公開版).jtd

Taro-2分探索木Ⅰ(公開版).jtd

Microsoft PowerPoint - algo ppt [互換モード]

Microsoft Word - 13

論理と計算(2)

Microsoft PowerPoint - kougi10.ppt

Microsoft PowerPoint - 6.pptx

Microsoft PowerPoint - 7.pptx

Microsoft PowerPoint - 05.pptx

PowerPoint Presentation

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

memo

PG13-6S

kiso2-09.key

Microsoft PowerPoint - algo ppt [互換モード]

cp-7. 配列

PowerPoint Presentation

Microsoft PowerPoint - ca ppt [互換モード]

alg2015-4r2.ppt

memo

第2回

次に示す数値の並びを昇順にソートするものとする このソートでは配列の末尾側から操作を行っていく まず 末尾の数値 9 と 8 に着目する 昇順にソートするので この値を交換すると以下の数値の並びになる 次に末尾側から 2 番目と 3 番目の 1

memo

Microsoft PowerPoint - 13approx.pptx

第2回

Taro-スタック(公開版).jtd

¥¢¥ë¥´¥ê¥º¥à¥¤¥ó¥È¥í¥À¥¯¥·¥ç¥ó ÎØ¹Ö #1

Taro-最大値探索法の開発(公開版

Microsoft PowerPoint - kougi9.ppt

Microsoft PowerPoint - IntroAlgDs pptx

DA13

memo

Taro-2分探索木Ⅱ(公開版).jtd

模擬試験問題(第1章~第3章)

Microsoft PowerPoint - 5.pptx

1. はじめに 二分木ヒープ 様々なアルゴリズムにおいて ある要素の集合またはリストから 最小 な要素を取り 出す必要がある そのような場合に使われる標準的データ構造が二分木ヒープ (binary heap) である あるオブジェクトO を考える そのオブジェクトは ラベル O. label と値

Quick Sort 計算機アルゴリズム特論 :2017 年度 只木進一

PowerPoint Template

2. データ構造ヒープに保存するデータは 番号付けられて保存される 従って リスト L として保存することとする 3. アルゴリズム 3.1. 要素の追加新しい要素の追加は リストの終端に置くことで開始する つまり 最下層の一番右 または新たに最下層を生成してその一番左となる この後 この要素を正し

Taro-リストⅠ(公開版).jtd

Microsoft Word - no206.docx

プログラミングI第10回

Microsoft PowerPoint - DA2_2019.pptx

Taro-再帰関数Ⅱ(公開版).jtd

C#の基本2 ~プログラムの制御構造~

program7app.ppt

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

gengo1-11

PowerPoint プレゼンテーション

Microsoft PowerPoint - IntroAlgDs ppt

Microsoft PowerPoint - IntroAlgDs ppt [互換モード]

Microsoft PowerPoint - ppt-7.pptx

COMPUTING THE LARGEST EMPTY RECTANGLE

概要 プログラミング論 変数のスコープ, 記憶クラス. メモリ動的確保. 変数のスコープ 重要. おそらく簡単. 記憶クラス 自動変数 (auto) と静的変数 (static). スコープほどではないが重要.

データ構造

2

Microsoft Word - no12.doc

Microsoft PowerPoint - IntroAlgDs pptx

Microsoft Word - 12

4-4 while 文 for 文と同様 ある処理を繰り返し実行するためのものだが for 文と違うのは while 文で指定するのは 継続条件のみであるということ for 文で書かれた左のプログラムを while 文で書き換えると右のようになる /* 読込んだ正の整数値までカウントアップ (for

PowerPoint プレゼンテーション

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

memo

CプログラミングI

プログラミング方法論 II 第 14,15 回 ( 担当 : 鈴木伸夫 ) 問題 17. x 座標と y 座標をメンバに持つ構造体 Point を作成せよ 但し座標 は double 型とする typedef struct{ (a) x; (b) y; } Point; 問題 18. 問題 17 の

関数の呼び出し ( 選択ソート ) 選択ソートのプログラム (findminvalue, findandreplace ができているとする ) #include <stdiu.h> #define InFile "data.txt" #define OutFile "surted.txt" #def

Microsoft PowerPoint - DA2_2017.pptx

main

今回のプログラミングの課題 ( 前回の課題で取り上げた )data.txt の要素をソートして sorted.txt というファイルに書出す ソート (sort) とは : 数の場合 小さいものから大きなもの ( 昇順 ) もしくは 大きなものから小さなもの ( 降順 ) になるよう 並び替えること

Microsoft PowerPoint - 計算機言語 第7回.ppt

Microsoft PowerPoint - ca ppt [互換モード]

JAVA入門

Microsoft Word - no11.docx

Microsoft PowerPoint - DA2_2018.pptx

Microsoft PowerPoint - kougi11.ppt

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

O(N) ( ) log 2 N

関数の呼び出し ( 選択ソート ) 選択ソートのプログラム (findminvalue, findandreplace ができているとする ) #include <stdio.h> #define InFile "data.txt" #define OutFile "sorted.txt" #def

PowerPoint プレゼンテーション

データ構造

PowerPoint プレゼンテーション

Microsoft PowerPoint - lec10.ppt

PowerPoint Presentation

文字数は1~6なので 同じ本数の枝を持つパスで生成される呪文の長さは最大で6 倍の差がある 例えば 上図のようなケースを考える 1サイクル終了した時点では スター節点のところに最強呪文として aaaaaac が求まる しかしながら サイクルを繰り返していくと やがてスター節点のところに aaaaaa

ohp11.dvi

r11.dvi

問題1 以下に示すプログラムは、次の処理をするプログラムである

Transcription:

算法数理工学 第 2 回 定兼邦彦

クイックソート n 個の数に対して最悪実行時間 (n 2 ) のソーティングアルゴリズム 平均実行時間は (n log n) 記法に隠された定数も小さい in-place ( 一時的な配列が必要ない ) 2

クイックソートの記述 分割統治法に基づく 部分配列 A[p..r] のソーティング. 部分問題への分割 : 配列 A[p..r] を 2 つの部分配列 A[p..q] と A[q+..r] に再配置する. A[p..q] のどの要素も A[q+..r] の要素以下にする. 添字 q はこの分割手続きの中で計算する. 2. 部分問題の解決 ( 統治 ): 部分配列 A[p..q] と A[q+..r] を再帰的にソート 3. 部分問題の統合 A[p..r] はすでにソートされているので何もしない 3

クイックソートのコード void QUICKSORT(data *A, int p, int r) { int q; if (p < r) { q = PARTITION(A,p,r); QUICKSORT(A,p,q); QUICKSORT(A,q+,r); main() { QUICKSORT(A,0,n-);

配列の分割 int PARTITION(data *A, int p, int r) // O(n) 時間 { int q, i, j; data x, tmp; x = A[p]; i = p-; j = r+; while () { do {j = j-; while (A[j] > x); do {i = i+; while (A[i] < x); if (i < j) { tmp = A[i]; A[i] = A[j]; A[j] = tmp; else { return j; 5

i A[p..r] 5 3 2 6 3 7 j 初期状態 : i と j は配列の範囲外 x = A[p] = 5 によって分割 x: 枢軸 (pivot) と呼ぶ 5 3 2 6 3 7 i j A[i] x A[j] x となる最初の i, j 7 は正しい分割位置にある 3 3 2 6 5 7 A[i] と A[j] を交換正しい分割位置になる i j 6

3 3 2 6 5 7 A[i] x A[j] x となる最初の i, j i j 3 3 2 6 5 7 A[i] と A[j] を交換 i j 3 3 2 6 5 7 j i i j となったので q = j を返す A[p..q] は x 以下 A[q+..r] は x 以上 7

PARTITION の正当性 PARTITION の返り値を q とする A[p..r] の分割後に満たされるべき条件 A[p..q] はある pivot x 以下 A[q+..r] は x 以上 p q < r q = r となると,QUICKSORT は停止しないため, どんな A に対しても q < r となることを保障する必要がある 8

初期状態は i < j do {j = j-; while (A[j] > x); do {i = i+; while (A[i] < x); の終了後 p i, j r A[j+..r] は x 以上 A[p..i-] は x 以下 A[i] x A[j] i < j のとき,A[i] と A[j] を交換すると A[j..r] は x 以上 A[p..i] は x 以下 i j のとき q = j 9

PARTITION の終了時に q = j = r とする while () のループを実行する毎に j は 以上減る 終了時に j = r ならばこのループは 度しか実行されていない しかし 回目のループでは x = A[p] なので i = p PARTITION は p < r の場合のみ呼ばれるので, 回目のループでは p = i < j = r つまり 回目のループでは終了しない よって PARTITION 終了時に q = r とはならない. つまり q < r 0

クイックソートの性能 クイックソートの実行時間は分割が平均化されているかどうかに依存 これは pivot の選択に依存 分割が平均化されていれば実行時間は漸近的にマージソートと同じ ( (n log n)) 最悪時は (n 2 )

平衡分割 PARTITION で常に 9 対 の比で分割されると仮定する T(n) = T(9n/0) + T(n/0) + (n) 再帰木の各レベルのコストは O(n) 再帰の深さは log 漸近的には中央で分割するのと同じ 分割の比が 99 対 でも同じ ( 定数比なら良い ) n lgn 0 9 6

ヒープソート O(n lg n) 時間アルゴリズム, in-place ヒープ (heap) と呼ばれるデータ構造を用いる ヒープはプライオリティキュー (priority queue) を効率よく実現する 7

ヒープ ヒープ : 完全 2 分木とみなせる配列 木の各節点は配列の要素に対応 木は最下位レベル以外の全てのレベルの点が完全に詰まっている 最下位のレベルは左から順に詰まっている 6 0 5 6 7 8 7 9 3 8 9 0 2 5 6 7 8 9 0 6 0 8 7 9 3 2 8

ヒープを表す構造体 typedef struct { int length; int heap_size; data *A; HEAP; // 配列 A に格納できる最大要素数 // ヒープに格納されている要素の数 // 要素を格納する配列 ヒープに後から要素を追加する場合があるとき, 配列 A は大きいものを確保しておく 9

length(h): 配列 A に格納できる最大要素数 heap_size(h): H に格納されているヒープの要素数 heap_size(h) length(h) 木の根 : A[] 節点の添え字が i のとき 親 PARENT(i) = i / 2 左の子 LEFT(i) = 2 i 右の子 RIGHT(i) = 2 i + 木の高さは (lg n) 6 0 5 6 7 8 7 9 3 8 9 0 2 20

ヒープ条件 (Heap Property) 根以外の任意の節点 i に対して A[PARENT(i)] A[i] つまり, 節点の値はその親の値以下 ヒープの最大要素は根に格納される 2

ヒープの操作 HEAPIFY: ヒープ条件を保持する. BUILD_HEAP: 入力の配列からヒープを構成する. 線形時間. HEAPSORT: 配列をソートする. O(n lg n) 時間. EXTRACT_MAX: ヒープの最大値を取り出す. O(lg n) 時間. INSERT: ヒープに値を追加する. O(lg n) 時間. 22

ヒープ条件の保持 HEAPIFY(H,i): A[i] を根とする部分木がヒープになるようにする. ただし LEFT(i) と RIGHT(i) を根とする 2 分木はヒープと仮定. void HEAPIFY(HEAP *H, int i) { int l, r, largest, heap_size; data tmp, *A; A = H->A; heap_size = H->heap_size; l = LEFT(i); r = RIGHT(i); if (l <= heap_size && A[l] > A[i]) largest = l; // A[i] と左の子で大きい else largest = i; // 方をlargestに if (r <= heap_size && A[r] > A[largest]) // 右の子の方が大きい largest = r; if (largest!= i) { tmp = A[i]; A[i] = A[largest]; A[largest] = tmp; // A[i] を子供と入れ替える HEAPIFY(H, largest); 23

HEAPIFY(A,2) 6 0 5 6 7 7 9 3 8 9 0 2 8 HEAPIFY(A,) 6 0 5 6 7 7 9 3 8 9 0 2 8 HEAPIFY(A,9) 6 0 5 6 7 8 7 9 3 8 9 0 2 2

HEAPIFY の実行時間 節点 i を根とする, サイズ n の部分木に対する HEAPIFY の実行時間 T(n) 部分木のサイズは 2n/3 以下 T(n) T(2n/3) + () T(n) = O(lg n) 高さ h の節点での実行時間は O(h) n/3 8 7 2 n/3 n/3 26

ヒープの構成 HEAPIFY では左右の部分木がヒープである必要がある 全体をヒープにするには,2 分木の葉の方からヒープにしていけばいい void BUILD_HEAP(HEAP *H, int n, data *A, int length) { int i; H->length = length; H->heap_size = n; H->A = A; for (i = n/2; i >= ; i--) { HEAPIFY(H,i); 27

A 3 2 6 9 0 8 7 3 5 6 7 8 2 9 0 6 9 0 8 7 HEAPIFY(A,5) 3 5 6 7 8 9 0 6 9 0 2 8 7 HEAPIFY(A,3) 3 5 6 7 2 6 9 0 8 9 0 8 7 HEAPIFY(A,) 0 5 6 7 6 9 3 8 9 0 2 8 7 HEAPIFY(A,2) 28

6 0 5 6 7 7 9 3 8 9 0 2 8 HEAPIFY(A,) 6 0 5 6 7 8 7 9 3 8 9 0 2 29

計算量の解析 O(lg n) 時間のHEAPIFYが O(n) 回 O(n lg n) 時間 ( 注 : これはタイトではない ) 高さ h の節点でのHEAPIFYは O(h) 時間 n 要素のヒープ内に高さ h の節点は高々 n/2 h+ 個 lgn lgn h 0 n h O( h) O n O h h 2 h 0 2 k n k x kx 0 ( x) 2 を用いる 30

最大値の削除 EXTRACT_MAX(S): 最大のキーを持つ S の要素を削除し, その値を返す data EXTRACT_MAX(HEAP *H) // O(lg n) 時間 { data MAX, *A; A = H->A; if (H->heap_size < ) { printf("error ヒープのアンダーフロー n"); exit(); MAX = A[]; A[] = A[H->heap_size]; // ヒープの最後の値を根に移動する H->heap_size = H->heap_size - ; HEAPIFY(H,); // ヒープを作り直す return MAX; 3

ヒープソート まずヒープを作る すると最大要素が A[] に入る A[] と A[n] を交換すると, 最大要素が A[n] に入る ヒープのサイズを つ減らしてヒープを維持する void HEAPSORT(int n, data *A) { int i; data tmp; HEAP H; BUILD_HEAP(&H,n,A,n); for (i = n; i >= 2; i--) { tmp = A[]; A[] = A[i]; A[i] = tmp; // 根と最後の要素を交換 H.heap_size = H.heap_size - ; HEAPIFY(&H,); 33

6 0 5 6 7 8 7 9 3 8 9 0 2 0 8 9 5 6 7 7 3 8 2 6 8 0 5 6 7 7 9 3 8 9 2 6 9 8 3 5 6 7 7 2 0 6 3

8 7 5 6 3 7 5 3 2 9 2 8 9 0 6 0 6 2 3 3 2 7 8 9 7 8 9 0 6 0 6 35

2 2 3 2 3 7 8 9 7 8 9 0 6 0 6 A 7 8 9 0 6 36

計算量 BUILD_HEAP: O(n) 時間 HEAPIFY: O(n lg n) 時間 全体で O(n lg n) 時間 37

要素の挿入 void INSERT(HEAP *H, data key) // O(lg n) 時間 { int i; data *A; A = H->A; H->heap_size = H->heap_size + ; if (H->heap_size > H->length) { printf("error ヒープのオーバーフロー n"); exit(); i = H->heap_size; while (i > && A[PARENT(i)] < key) { A[i] = A[PARENT(i)]; i = PARENT(i); A[i] = key; 38

要素の削除 削除したい値がヒープ中のどこに格納されているか分かっているとする void DELETE(HEAP *H, int i) // O(lg n) 時間 { data *A; A = H->A; if (i < i > H->heap_size) { printf("error 範囲エラー (%d,%d) n",i,h->heap_size); exit(); while (i > ) { A[i] = A[PARENT(i)]; // A[i] の祖先を つずつ下におろす i = PARENT(i); A[] = A[H->heap_size]; // 根が空になるので, 最後の値を根に持っていく H->heap_size = H->heap_size - ; HEAPIFY(H,); 0

ヒープに格納する値が から n の整数で, 重複は無いとする 整数の配列 I[..n] を用意する I[x] = j のとき, 整数 x がヒープの A[j] に格納されていることを表す I[x] = - ならば x は格納されていないとする 要素の移動を行うときは同時に I も更新する A[j] = x I[x] = j が常に成り立つ ( ように更新 ) 2

プライオリティキュー 要素の集合 S を保持するためのデータ構造 各要素はキーと呼ばれる値を持つ 次の操作をサポートする INSERT(S,x): S に要素 x を追加する MAXIMUM(S): 最大のキーを持つ S の要素を返す EXTRACT_MAX(S): 最大のキーを持つ S の要素を削除し, その値を返す 3