高速ソートと 安定結婚問題 高速ソート 単純なソートアルゴリズム バブルソート O(n2) 選択ソート O(n2) 挿入ソート O(n2) もっと高速なソートアルゴリズムは? 計算量が O(n log n) のソートアルゴリズム クイックソート ヒープソート マージソート この中でクィックソートが最速 (ランダムデータに対して.不得手な場合もある) クイックソートの原理 考え方: 分割統治法(divide and conquer) まず、配列中の適当な要素を選ぶ → これを枢軸(pivot)と呼ぶ 次のように要素を並べ替える → これを分割(partition)という a[0] ・・・・・・・・・・ a[v-1] a[v] a[v+1] ・・・ a[n-1] a[v]より小(以下) a[v] a[v]より大(以上) では、a[0],・・・,a[v-1]の部分と、 a[v+1],・・・,a[n-1]の部分は どうするか? ↓ ピボットの選択 →分割を再帰的に繰り返せばよい! クィックソートのアルゴリズム概観 ①ソートするデータ区間のデータを得る ②区間内のデータ数が2以下の時 2-1:データ数が1以下の時なにもしない 2-2:データ数が2の時,必要なら交換 ③区間内のデータ数が3以上の時 3-1:区間内でピボットを選ぶ(便宜的に右端) 3-2:区間内で,ピボットより小さい区間(左半 分)と大きい区間(右半分)に分割する 3-3:3-2の両区間を再帰的処理する /* 配列aのうち a[l]~a[r] を整列する */ quick_sort ( int a[ ], int l, int r ) { if( 整列する要素が一つのみである ) return; 適当な要素 a[v] を枢軸にして、 a[v] より小さい要素を a[l]~a[v-1] に集め、 a[v] より大きい要素を a[v+1]~a[r] に集める quick_sort ( a, l, v-1 ); /* 左の部分を整列する */ quick_sort ( a, v+1, r ); /* 右の部分を整列する */ } 分割のアルゴリズム 0a.一番右の要素を枢軸に選ぶ 0b.ポインタ i を左端に、ポインタ j を枢軸の すぐ左に設定する 1.枢軸より大きな要素が見つかるまで i を右へスキャン 2.枢軸より小さな要素が見つかるまで j を左へスキャン 3. i が指す要素と j が指す要素を交換する 4. i と j がぶつかるまで1~3を繰り返す 5. j の指す要素と枢軸と交換する i j 55 3 74 20 13 前半に<30,後半に>30を置く.それに反するものを入れ替える 55 3 13 46 30 j 20 13 87 46 30 3 74 j 20 55 87 46 30 3 i 74 55 87 46 30 55 87 46 30 j 20 j i 13 87 74 i 13 ピボット 3 20 74 左スキャンと右スキャンが交錯したらピボットをそこに置く→@ピボットの左にピボットより小さい値,右に大きい値があるはず j 13 3 20 v i 30 55 87 46 74 再帰版クイックソート /* 配列a[l]~a[r]を分割する。枢軸の添え字を返す */ int partition( int a[ ], int l, int r ) { int i, j, pivot, t; i = l – 1; j = r; /* ポインタ i と j を初期化する */ pivot = a[r]; /* いちばん右端の要素を枢軸にする */ for( ; ; ) { /* ポインタ i と j とがぶつかるまで繰り返す */ while( a[++i] < pivot ) ; /* ポインタ i を右へ進める */ while( i < j && pivot < a[j] ) ; /* ポインタ i を左へ進める */ if ( i >= j ) break; /* ポインタ i と j がぶつかったらループを抜ける */ t = a[i]: a[i] = a[j]; a[j] = t; /* i の指す要素と j の指す要素を交換する */ } t = a[i]: a[i] = a[r]; a[r] = t; /* a[i] と枢軸を交換する */ return i; } クイックソートの計算量 最適な分割: pivot がほぼ中央に来る → ほぼ半分ずつに分割される → 要素1までの分割数をpとすると 2p =n ,よってp=log 2n回分割が必要 部分列の個数はn個. → 計算量は O(n log n) 最悪の分割:ピボット が端に来る 枢 軸 枢軸より小さい要素 k-1個 ↓ 分割のレベル数(深さ)は n ↓ 計算量は O(n2) 枢 軸 枢軸より大きい 要素 0個 まとめ: クイックソートの計算量は 最良 O(n log n) 平均も! 最悪 O(n2) クイックソートの改善方法 部分配列の長さが10程度以下になったら、 挿入ソートに切り替える k1・n2 >? k2・n log2n (k1<k2) 俗に quicker sort 最悪の場合を回避する 部分配列の右端、中央、左端の3つのうちの 中央値を枢軸に 再帰の深さを減らす → 左右の部分配列のうち、 短いほうから先に処理をする → 再帰の深さは最大 log2n 程度 → 非再帰版 → 再帰の処理をスタックを利用して 自分で行なう。 安定結婚問題 安定結婚問題 フィーリングカップル5対5 (講義1回目) 1 2 3 ① ② ③ 4 ④ 5 ⑤ 安定結婚問題 ・ 最初の論文 → [Gale & Shapley 1962] - アメリカの研修医配属問題がきっかけ。 - どんな例題にも、必ず安定マッチングが存在する。 - 安定マッチングを多項式時間で見つけることができる。 (Gale-Shapley アルゴリズム) ・様々な類似問題 - 安定ルームメイト問題 - Residents/Hospitals 問題 ・最近、様々な新種の問題 ・実世界での応用 研修医配属 NRMP (National Resident Matching Program) CaRMS (Canadian Resident Matching Service) SPA (Scottish Pre-registration house officer Allocations) JRMP (Japanese Resident Matching Program) 不安定結婚とは • カップルでない男女双方ともに互いに対する 好感度が自分のカップル相手よりも高い場合、 そのカップルは持続せず解消してしまう。 →不安定なカップル • 上記の状況が全く発生していない →安定なカップル 力任せで安定結婚問題を解くアルゴリズム コンピュータは速いから、すべての5組カップルを生成して (5!=5*4*3*2*1=120)、それが安定か不安定かを調べればいい? N=11 1秒 N=12 4秒 N=13 2分52秒 N=14 42分30秒 N=15 11時間 ・すべての組み合わせを作る計算量は ・安定性をチェックする計算量は ・よって総計算量は ・N=16のときの大よその実行時間は N! N*N N!*N*N 1週間 もっと速いアルゴリズムは? • なぜ遅い? ⇒すべての組合せを生成して,毎回浮気のチェックをしているので, 入力データ数Nの壁に阻まれる生成検査法(Generate and Test) ⇒一発で解が作れないか? ⇒それは無理 ⇒でも無意味な組み合わせから始めるのはよくない ⇒どのような組合せなら作成可能で無駄が少ないか? ①理想的な状態(浮気が起こらない組合せ)から始めてみてはどうか? 理想状態=第一希望の異性とのカップル 相手にパートナーがいるか否かを無視して、とりあえず強引に第一希望に 申し込む。既にパートナーがいれば、その好感度を比較して、既存パート ナーの好感度が高ければ、申込を破棄、低ければ、パートナーを解消して、 新パートナーを作る。 もっと速いアルゴリズムは? ②乗り換え発生時:カップル解消された人は困りますよね。その 人は、一つ好感度が低い人に新たにカップルを申し入れて、 先程と同様の処理をする。 ③カップル解消が起きて一人はじかれると、 入れ替え(玉突き現象)が際限なく起こらない? ⇒これは大丈夫。好感度が一つ低い相手を選ぶので、 一度のカップル解消で最大入れ替え回数は?回 下記の例で効率的アルゴリズムを実行してみると 男子 ④③②⑤① ③②⑤①④ ④②⑤③① ④⑤③①② ②③④①⑤ × 41325 13524 35124 42135 女子 手順1 男性1 ④ 手順2 男性1 ④ 男性2 ③ 男性1 ④ 男性2 ③ 男性3 ④→2 ? ... ? ... 手順3 手順4? ... 43215 フィーリングカップル5対5 の解答 男子 ④③②⑤① ③②⑤①④ ④②⑤③① ④⑤③①② ②③④①⑤ × 41325 13524 35124 42135 43215 女子 手順1 男性1:④ 手順2 男性1:④ 男性2:③ 手順3 男性1:④ 男性2:③ 男性3:④→② 手順4 男性1:④→③ 男性2:③→②→⑤ 男性3:④→② 男性4:④ 手順5 男性1:④→③→② 男性2:③→②→⑤→① 男性3:④→②→⑤ 男性4:④ 男性5:②→③ より形式的に安定結婚問題を考えると 入力:男性N人 女性N人 希望リスト N=5の例 男性: 1,2,3,4,5 女性: a,b,c,d,e 男性の希望リスト 女性の希望リスト 1: a c b d e a: 2 1 3 4 5 2: c a e b d b: 2 1 4 5 3 3: b a e d c c: 1 2 3 5 4 4: c b d e a d: 3 1 4 2 5 5: c d b e a e: 4 3 1 2 5 出力 :男女間の不安定マッチングの例 1: a c b d e a: 2 1 3 4 5 12: c a e b d ab: 2 1 4 5 3 23: b a e d c bc: 1 2 3 5 4 34: c b d e a cd: 3 1 4 2 5 45: c d b e a de: 4 3 1 2 5 5 1 と女性 c は ブロッキングペア e 男性 ブロッキングペアの存在しないマッチング: 安定マッチング これは解の条件を満たしていない。 安定結婚問題: 与えられた入力から、安定マッチングを見つける。 The Gale-Shapley Algorithm [Gale & Shapley 1962] (Men-propose) 1: a c b d e a: 2 1 3 × 2: c a e b d b: 2 1 4 e d c c: 1 2 3 4: b × a × c b × d e a d: 3 1 4 2 5 5: c × b e a e: 4 3 1 2 5 3: d 4 5 3 × 5 × 4 × 5 Theorem [Gale & Shapley 1962, Gusfield & Irving 1989] The Gale-Shapley algorithm finds a stable matching.
© Copyright 2024 ExpyDoc