クイックソートは、適当な値(これを pivot という)を選び、その pivot よりも大きい値を配列の右側に移動し、pivot よりも小さい値を配列の左側に移動して、配列を 2 つに分割する。次に、分割された 2 つの配列それぞれに対して、pivot を選びさらに分割を行う。分割を再帰的に行なって行ったとき、最終的には整列済みの部分配列が得られる。最後にこれらの部分配列を結合すれば、整列済みの配列が得られる。クイックソートは、データの比較回数と交換回数が、他のソートアルゴリズムに比べて少ないので、値がランダムな配列を整列する場合に、効率が最も良いと言われている。
C/C++ でクイックソートを実装する上で、具体的に次のような手順を踏む。
- n 個の要素を持つ入力配列 A[1..n] の最後要素を pivot とする。すなわち pivot = A[n] とする。
- j = 1, 2, ..., i, ..., n-1 それぞれに対して、A[j] と pivot (=A[n]) を比較し、A[j] が大きければ、それを配列の左側の要素を入れ替える。この入れ替えが終わると、pivot は i の位置に移動する。
- 位置 i の左側を部分配列として、その部分配列の最後の要素を pivot として、手順 2 を行う。
- 位置 i の右側を部分配列として、その部分配列の最後の要素を pivot として、手順 2 を行う。
#include <stdio.h>
void swap(int* a, int* b)
{
int t = *a;
*a = *b;
*b = t;
}
int partition (int array[], int l, int r) {
int pivot = array[r];
int i = (l - 1);
for (int j = l; j <= r - 1; j++) {
if (array[j] <= pivot) {
i++;
swap(&array[i], &array[j]);
}
}
swap(&array[i + 1], &array[r]);
return (i + 1);
}
void quickSort(int array[], int l, int r) {
if (l < r) {
int pivot = partition(array, l, r);
quickSort(array, l, pivot - 1);
quickSort(array, pivot + 1, r);
}
}
int main (void) {
int i;
int array[10] = {3, 6, 1, 7, 2, 0, 4, 5, 9, 8};
printf(" array: ");
for (i = 0; i < sizeof(array) / sizeof(array[0]); i++) {
printf("%d ", array[i]);
}
printf("\n");
quickSort(array, 0, sizeof(array) / sizeof(array[0]) - 1);
printf("sorted array: ");
for (i = 0; i < sizeof(array) / sizeof(array[0]); i++) {
printf("%d ", array[i]);
}
printf("\n");
return 0;
}
References
- Introduction to Algorithms, Third Edition.
- C++ Programming Language. GeeksforGeeksk