名前の通り「並び替えが早い」アルゴリズムです。
※全てにおいて早いわけではないそうです。
アルゴリズム
- 適当な数(ピボット:pivot)を選択する。(データ総数の中央値が望ましい)
- ピボットより小さい数を前方、大きい数を後方に移動させる(分割)
- 二分割されたデータをそれぞれソートする。
一例
- ピボットとして一つ選びそれをPとする。
- 左から順に値を調べ、P以上のものを見つけたらその位置をiとする。
- 右から順に値を調べ、P以下のものを見つけたらその位置をjとする。
- iがjより左にあるのならばその二つの位置を入れ替え、2に戻る。ただし、次の2での探索はiの一つ右、次の3ではjの一つ左から行う。
- 2に戻らなかった場合、iの左側を境界に分割を行って二つの領域に分け、そのそれぞれに対して再帰的に1からの手順を行う。要素数が一以下の領域ができた場合、その領域は確定とする。
以下のような数列データがあるとします。
5 14 10 15 13 4 2 7 19 12
まず、この10個の要素の中からピボットを選択します。
5 14 10 15 13 4 2 7 19 12
まず、この10個の要素の中からピボットを選択します。
中央値((開始位置+終了位置)/2)をピボットとします。
このデータの場合は以下の様になります。
(0+9)/2=4(小数点切り捨て)
4番目の要素「13」をピボットとします。
5 14 10 15 13 4 2 7 19 12
データの先頭からピボット以上のデータを探します。
データの末尾からピボット以下のデータを探します。
その値があれば、その値同士を交換していきます。
そして、先頭と末尾の探索が交差するまでこの操作を続けます。
それでは先頭から探索します。
5 14 10 15 13 4 2 7 19 12
5 14 10 15 13 4 2 7 19 12
5は13以上ではないので次へ
5 14 10 15 13 4 2 7 19 12
5 14 10 15 13 4 2 7 19 12
14は13以上なので、交換する要素です。
次は末尾から探索します。
5 14 10 15 13 4 2 7 19 12
12は13以下なので、交換する要素です。
12は13以下なので、交換する要素です。
それでは交換しましょう。
5 12 10 15 13 4 2 7 19 14
交差するまでこの処理を続けます。
5 12 10 15 13 4 2 7 19 14 10は13以上ではないので次へ
5 12 10 15 13 4 2 7 19 14 15は13以上なので、交換する要素です。
5 12 10 15 13 4 2 7 19 14 19は13以下ではないので次へ
5 12 10 15 13 4 2 7 19 14 7は13以下なので、交換する要素です。
5 12 10 7 13 4 2 15 19 14 交換
5 12 10 7 13 4 2 15 19 14 ピボットである13が交換要素になりました。
5 12 10 7 13 4 2 15 19 14 2は13以下なので、交換する要素です。
5 12 10 7 2 4 13 15 19 14 交換
5 12 10 7 2 4 13 15 19 14 13は13以上なので、交換する要素です。
5 12 10 7 2 4 13 15 19 14 13は13以下なので、交換する要素です。
5 12 10 7 2 4 13 15 19 14 13は13以下なので、交換する要素です。
13が交換する要素になりますが、先頭と末尾が交差したので処理を終了します。
ピボットを軸として左右に要素を分割します。
5 12 10 7 2 4 13 15 19 14
そして左右別々に再帰的にソートを行います。
これを繰り返して、整列すべきデータ数列が一つになるまで行えば、昇順にソートされます。
▼ 左側から
5 12 10 7 2 4
Pivot = (0+5)/2 = 2
2番目の要素「10」をピボットとします。
5 12 10 7 2 4
5 12 10 7 2 4 5は10以上ではないので次へ
5 12 10 7 2 4 12は10以上なので交換する要素
5 12 10 7 2 4 4は10以下なので交換する要素
5 4 10 7 2 12 交換
5 4 10 7 2 12 10は10以上なので交換する要素
5 4 10 7 2 12 2は10以下なので交換する要素
5 4 2 7 10 12 交換
5 4 2 7 10 12 交差したので終了
5 4 2 7 10 12 分割
▼ 左側から
5 4 2 7
Pivot = (0+3)/2 = 1
1番目の要素「4」をピボットとします。
5 4 2 7
5 4 2 7 5は4以上
5 4 2 7 2は4以下
2 4 5 7 交換
2 4 5 7 交差したので終了
2 4 5 7 分割
▼ 左側
2 要素数1なので終了
▼ 右側
5 7
Pivot = (0+1)/2 = 0
0番目の要素「5」をピボットとします。
5 7
5 7 交差したので終了
左側の探索が終了して「2 4 5 7」となりました。
▼ 右側
12 要素数1なので終了
左側の探索が終了して「2 4 5 7 10 12」となりました。
ピボットを軸として左右に要素を分割します。
5 12 10 7 2 4 13 15 19 14
そして左右別々に再帰的にソートを行います。
これを繰り返して、整列すべきデータ数列が一つになるまで行えば、昇順にソートされます。
▼ 左側から
5 12 10 7 2 4
Pivot = (0+5)/2 = 2
2番目の要素「10」をピボットとします。
5 12 10 7 2 4
5 12 10 7 2 4 5は10以上ではないので次へ
5 12 10 7 2 4 12は10以上なので交換する要素
5 12 10 7 2 4 4は10以下なので交換する要素
5 4 10 7 2 12 交換
5 4 10 7 2 12 10は10以上なので交換する要素
5 4 10 7 2 12 2は10以下なので交換する要素
5 4 2 7 10 12 交換
5 4 2 7 10 12 交差したので終了
5 4 2 7 10 12 分割
▼ 左側から
5 4 2 7
Pivot = (0+3)/2 = 1
1番目の要素「4」をピボットとします。
5 4 2 7
5 4 2 7 5は4以上
5 4 2 7 2は4以下
2 4 5 7 交換
2 4 5 7 交差したので終了
2 4 5 7 分割
▼ 左側
2 要素数1なので終了
▼ 右側
5 7
Pivot = (0+1)/2 = 0
0番目の要素「5」をピボットとします。
5 7
5 7 交差したので終了
左側の探索が終了して「2 4 5 7」となりました。
▼ 右側
12 要素数1なので終了
左側の探索が終了して「2 4 5 7 10 12」となりました。
▼ 右側
13がピボットの時の右側を探索
15 19 14
Pivot = (0+2)/2 = 1
1番目の要素「19」をピボットとします。
15 19 14
15 19 14 15は19以下なので次へ
15 19 14 19は19以上
15 19 14 14は19以下
15 14 19 交換
15 14 19 分割 ピボットである19の右側には要素がないので右側は終了
▼ 左側
15 14
Pivot = (0+1)/2 = 0
0番目の要素「15」をピボットとします。
15 14
15 14 15は15以上
15 14 14は15以下
14 15 交換 交差したので終了
右側の探索が終了して「14 15 19」となりました。
左右すべての探索が終了しました。
結果「2 4 5 7 10 12 13 14 15 19」と昇順にソートされました。
Javaのプログラムは以下の様な形になりました。
13がピボットの時の右側を探索
15 19 14
Pivot = (0+2)/2 = 1
1番目の要素「19」をピボットとします。
15 19 14
15 19 14 15は19以下なので次へ
15 19 14 19は19以上
15 19 14 14は19以下
15 14 19 交換
15 14 19 分割 ピボットである19の右側には要素がないので右側は終了
▼ 左側
15 14
Pivot = (0+1)/2 = 0
0番目の要素「15」をピボットとします。
15 14
15 14 15は15以上
15 14 14は15以下
14 15 交換 交差したので終了
右側の探索が終了して「14 15 19」となりました。
左右すべての探索が終了しました。
結果「2 4 5 7 10 12 13 14 15 19」と昇順にソートされました。
Javaのプログラムは以下の様な形になりました。
public class quick_sort { static void quickSort(int[] a, int left, int right) { /* クイックソート * a : 要素配列 p : ピボット(データ中央値) * left : 開始位置 i : 左側の配列位置 * right : 終了位置 j : 右側の配列位置 */ int i=left, j=right, t, p=a[(i+j)/2]; while(true) { while(a[i] < p) i++; // ピボット以上の値を先頭から探索 while(p < a[j]) j--; // ピボット以下の値を末尾から探索 if(i>=j)break; // 探索位置i,jが交差したら終了 t=a[i];a[i]=a[j];a[j]=t; // 左右の値を交換 i++; j--; // 探索位置を1つずらす } // 分割 // 左側を再帰的にソート if(left < i-1){ quickSort(a, left, i-1); } // 右側を再帰的にソート if(j+1 < right){ quickSort(a, j+1, right); } } public static void main(String[] args) { int[] a = {8, 10, 4, 14, 7, 5, 2, 1, 11, 13}; quickSort(a, 0, a.length-1); for(int i:a) { System.out.print(i+" "); } System.out.println(); } }
0 件のコメント:
コメントを投稿