1 データのブロック分割 2 各ブロックごとの処理(並べ換え) 3 ブロックの統合であり、クイックソートでは特に1のデータの分割にアルゴリズムのよさの秘密が隠されている。例を用いてクイックソートのアルゴリズムを解説しよう。
48 65 10 36 83 5 21 72ステップ01
48 65 10 36 83 5 21 72ステップ02
21 65 10 36 83 5 48 72さらに、ステップ02を続けると、5と65が入れ替わる。
21 5 10 36 83 65 48 72以下、同様な操作を繰り返し、注目している点が交差するまで行なう。すると
21 5 10 36 83 65 48 72が得られる。これは、基準値とした位置(左から4番目)を境に、左右ブロックに分割したことになる。左側には4番目のデータ(36)よりも小さいデータ、右側には大きいデータとなる。
ステップ1ー1
左側のブロックに対して、ステップ01、02を行なう。
21 5 10 5 | 21 10よって、5と21,10とに分割できる。
ステップ1ー1ー1
さらに、左側についてステップ01、02を行なう。この場合、5だけなのでなにもしない。
ステップ1ー1ー2
右側の21,10についてステップ01、02を行なう。
上記ステップ1ー1ー1、1ー1ー2により、
5 10 21が得られる。
ステップ1ー2
83,65,48,72について同様にステップ01、02を行なう。よって、
5 10 21 36 48 65 72 83が得られる。
基準点としたデータが、左、右いずれかのブロックに含まれる時と含まれない時がある。その詳細についてはプログラム6−4を見ていただきたい。ここでは、アルゴリズムの大体の考え方を理解できればよいと考えている。
クイックソートのプログラムは以下のようである。
1: void QuickSort( int data[], int upper, int lower ) { 2: int mid, tmp, i, j; 3: 4: i = upper; 5: j = lower; 6: mid = data[(lower+upper)/2]; 7: do { 8: while( data[i] < mid ) i++; 9: while( mid < data[j] ) j--; 10: if( i <= j ) { 11: tmp = data[i]; 12: data[i] = data[j]; 13: data[j] = tmp; 14: i++; 15: j--; 16: } 17: } while( i <= j ); 18: if ( upper < j ) QuickSort(data, upper, j); 19: if ( i < lower ) QuickSort(data, i, lower); 20: }Quicksortメソッドは、プログラム内部でさらに自分自身を呼んでいる。つまり再帰的なアルゴリズムとなっている。先に示した例のデータを用いて実行の様子を表現すると、下記のような構造となっている。
( 48 65 10 36 83 5 21 72 ) | |QuickSort(1,8) −−−−− +−−−−−−− | | | ( 21 5 10 ) ( 36 ) ( 83 65 48 72 ) | | QuickSort(1,3)| |QuickSort(5,8) −−− +−− −−+−−−− | | | | ( 5 ) ( 21 10 ) ( 48 ) ( 65 ) ( 83 72 ) | | QuickSort(2,3)| |QuickSort(7,8) −−+−− −−+−− | | | | ( 10 ) ( 21 ) ( 72 ) ( 83 )よって分割したブロックを統合すると、
5 10 21 36 48 65 72 83となる。
クイックソートの計算時間量を評価してみよう。今回は、プログラム中の11〜13の実行回数をカウントすることで、オーダーを求めることにする。
1段目 QuickSort(1,n)では、入れ替えの起こる確率を1/2とすると約n/2回 実行される。 2段目 QuickSort(1,n/2)、QuickSort(n/2,n)では、入れ替えの起こる確率を1/2と するとそれぞれ約n/4回実行される。二つの回数を合わせると、約n/2回 の実行となる。 3段目 4つの関数QuickSort(1,n/4)、QuickSort(n/4,n/2)、QuickSort(n/2,3n/4)、 QuickSort(3n/4,n)が実行されそれぞれ約n/8回の実行となる。これらを合 わせると約n/2回の実行となる。 4段目 同様に考えると8回のQuickSort関数を実行し、それぞれ約n/16回実行。 合わせると約n/2回の実行回数となる。以上から、各段階では約n/2回の入れ替えが起こることがわかる。