今回はクイックソートを実装してみたいと思います。
クイックソートは考え方は難しくないとよく言いますが、僕は頭がこんがらがってめちゃくちゃ悩みました。
考え方は、「基準の数字を選び、それより大きい数字と小さい数字を探し、見つかったら位置を交換する。これを繰り返し、基準の数字よりも大きな数字グループと小さな数字グループに分け、前述の操作を行う。この操作をグループが2つに分けられなくなるまで同じ操作を繰り返す」です。
簡潔にまとめたかったんですけど上手な言い方が思い浮かびませんでした。。。
クイックソートは分割統治法(問題を分割して、その問題を解くことで結果的に大問題を解く手法)を使った代表例になります。
コードはこのようになります。
import java.util.*;
public class Algorithm {
public static void main(String[] args){
// ランダム配列を生成
Random r = new Random();
int[] array = new int[10];
for (int i = 0; i < array.length; i++) {
array[i] = r.nextInt(50);
}
print(array);
QuickSort(array, 0, array.length - 1);
print(array);
}
static void QuickSort(int[] array, int left, int right){
if (left <= right){
int half = array[(left + right) / 2]; // 中央値を取得
int l = left;
int r = right;
while (l <= r){
// 右から調べて、halfより大きい数があるまで走査し、該当するインデックスを取得
while(array[l] < half){
l++;
}
// 左から調べて、halfより小さい数があるまで走査し、該当するインデックスを取得
while (array[r] > half){
r--;
}
// もし該当するインデックスが見つかったら値を交換する
if (l <= r){
int tmp = array[l];
array[l] = array[r];
array[r] = tmp;
// 交換後はさらに探索を行う
l ++;
r --;
}
}
// whileを抜けたら、分割した左側に同じような操作を行う
QuickSort(array, left, r);
// 分割した右側に同じような操作を行う
QuickSort(array, l, right);
}
}
static void print(int[] array) {
for (int i = 0; i < array.length; i++) {
if (i != 0) {
System.out.print(" ");
}
System.out.print(array[i]);
}
System.out.println();
}
}
難しいと思っていましたが、理解すれば簡単ですね!
今回は基準の値として中央値を指定していますが、array[left](もしくはarray[right])として端の値をとっても動きます。ここはお好みですね。
次回はマージソートを学んでいきます!