クイックソートとは
実用上最も高速といわれる有名なアルゴリズム。
- 分割統治法による整列アルゴリズム
- 列を2つに分割して、それぞれを整列していく。
手順:
- pivot(軸となる要素)を1つ選び、pivotより小さい部分列と大きい部分列に分ける
- 小さい側をクイックソート
- 大きい側をクイックソート
サンプルプログラム
ここでは、int型の配列を、クイックソートを用いて小さい順に整列する。
quick_sort.c
#include<stdio.h>
/* 値を入れ替える関数 */
void swap (int *x, int *y) {
int temp; // 値を一時保存する変数
temp = *x;
*x = *y;
*y = temp;
}
/***
* pivotを決め、
* 全データをpivotを境目に振り分け、
* pivotの添え字を返す
***/
int partition (int array[], int left, int right) {
int i, j, pivot;
i = left;
j = right + 1;
pivot = left; // 先頭要素をpivotとする
do {
do { i++; } while (array[i] < array[pivot]);
do { j--; } while (array[pivot] < array[j]);
// pivotより小さいものを左へ、大きいものを右へ
if (i < j) { swap(&array[i], &array[j]); }
} while (i < j);
swap(&array[pivot], &array[j]); //pivotを更新
return j;
}
/* クイックソート */
void quick_sort (int array[], int left, int right) {
int pivot;
if (left < right) {
pivot = partition(array, left, right);
quick_sort(array, left, pivot-1); // pivotを境に再帰的にクイックソート
quick_sort(array, pivot+1, right);
}
}
int main (void) {
int array[10] = { 2, 1, 8, 5, 4, 7, 9, 0, 6, 3 };
int i;
printf("Before sort: ");
for (i = 0; i < 10; i++) { printf("%d ", array[i]); }
printf("\n");
quick_sort(array, 0, 9);
printf("After sort: ");
for (i = 0; i < 10; i++) { printf("%d ", array[i]); }
printf("\n");
return 0;
}
実行結果
Before sort: 2 1 8 5 4 7 9 0 6 3
After sort: 0 1 2 3 4 5 6 7 8 9
性能
- 平均計算量は$O(n\log n)$
- 最悪計算量は$O(n^2)$
- pivotにより列を2分割するが、これが左右に偏ってしまうと分割数が多くなり時間がかかる
- できるだけ2等分に近い分け方をすると、効率が良くなる
- 中央値をpivotにするとか