クイックソート
Pivotを確定位置へ置き、両partitionを再帰的にsortします。
クイックソートとは?
Pivotを確定位置へ置き、両partitionを再帰的にsortします。
Pivotを基準にvalueをpartitionします。
重要なポイント
- 空、1要素、重複、ソート済み入力をテストします。
- 正しさと最適化を分けます。
- 実務ではstandard libraryを優先します。
クイックソートのビジュアライザー
O(n log n)再生またはステップを使って、比較とデータ移動を順に確認できます。
CとC++のコード例
C
main.c
#include <stdio.h>
void swap(int *left, int *right) {
int temporary = *left;
*left = *right;
*right = temporary;
}
int partition(int *values, int low, int high) {
int pivot = values[high];
int boundary = low;
for (int scan = low; scan < high; ++scan) {
if (values[scan] < pivot) {
swap(&values[boundary++], &values[scan]);
}
}
swap(&values[boundary], &values[high]);
return boundary;
}
void quick_sort(int *values, int low, int high) {
if (low >= high) return;
int pivot = partition(values, low, high);
quick_sort(values, low, pivot - 1);
quick_sort(values, pivot + 1, high);
}
int main(void) {
int values[] = {9, 4, 7, 3, 10, 5};
quick_sort(values, 0, 5);
for (int index = 0; index < 6; ++index) {
printf("%d ", values[index]);
}
}
3 4 5 7 9 10
C++
main.cpp
#include <algorithm>
#include <iostream>
#include <vector>
template<class Iterator>
void quick_sort(Iterator first, Iterator last) {
if (last - first < 2) return;
auto pivot = *(last - 1);
auto middle = std::partition(first, last - 1,
[pivot](int value) { return value < pivot; });
std::iter_swap(middle, last - 1);
quick_sort(first, middle);
quick_sort(middle + 1, last);
}
int main() {
std::vector values{9, 4, 7, 3, 10, 5};
quick_sort(values.begin(), values.end());
for (int value : values) {
std::cout << value << ' ';
}
}
3 4 5 7 9 10
CとC++の比較
平均O(n log n)、悪いpivotではO(n²)。C++はstd::partitionでpartition処理を表します。
C
loop、pointer、length、bufferを明示します。
C++
iteratorとalgorithmが操作と格納方法を分離します。
練習課題
両方を実行して変更し、言語ごとの保証を確認します。
- 各比較を手で追跡します。
- 重複と極値をテストします。
- standard libraryとbenchmarkします。