C++で実装するコムソート(Comb Sort)アルゴリズムの解説とサンプルコード
コムソート(Comb Sort)は、バブルソートやカクテルソートに似たソートアルゴリズムです。大きな特徴は、隣接する要素同士を比較するのではなく、一定間隔(ギャップ)だけ離れた要素同士を比較していく点にあります。
ギャップは [n/c] として定義されます。ここで n は要素数、c は縮小係数(シュリンクファクター)です。各反復処理が終わるたびにギャップを c で割り、切り捨てていきます。これを繰り返し、最終的にはギャップが1、つまり隣接する要素同士の比較になります。
入力:5 3 4 2 1 出力:1 2 3 4 5
コムソートの仕組み
コムソートでは、まず大きめのギャップで離れた要素同士を比較・交換します。これにより、配列の後ろ側にある小さな値(いわゆる「ウサギ」)や前側にある大きな値(「カメ」)を素早く移動させることができ、バブルソートの弱点を克服しています。
具体的な流れは以下の通りです。
- 初期ギャップを要素数 n に設定します。
- 各パスの前に、ギャップを gap × 10 / 1.3 で更新します(縮小係数は一般的に 1.3 が推奨されています)。
- ギャップが 9 または 10 になった場合は 11 に設定します(これは経験的にソート効率を上げるための調整です)。
- ギャップが 1 未満になった場合は 1 に設定します。
- ギャップ分離れた要素同士を比較し、順序が逆なら交換します。交換が一度でも発生したらフラグを立てます。
- ギャップが 1 になり、かつ交換が一切発生しなくなった時点でソート完了です。
C++による実装例
以下は、コムソートを C++ で実装したサンプルコードです。
#include <iostream>
using namespace std;
void combsort(int a[], int n) {
int i, j, gap, swapped = 1;
int temp;
gap = n;
while (gap > 1 || swapped == 1) {
gap = gap * 10 / 1.3; // ギャップを縮小
if (gap == 9 || gap == 10) {
gap = 11; // 効率化のための特別な調整
}
if (gap < 1) {
gap = 1; // 最小ギャップは1
}
swapped = 0;
for (i = 0, j = gap; j < n; i++, j++) {
if (a[i] > a[j]) { // 順序が逆なら交換
temp = a[i];
a[i] = a[j];
a[j] = temp;
swapped = 1;
}
}
}
}
int main() {
int n, i;
int arr[] = { 5, 3, 4, 2, 1 };
n = 5;
combsort(arr, n);
for (i = 0; i < n; i++) {
cout << arr[i] << "\t";
}
return 0;
}実行結果
1 2 3 4 5
計算量について
コムソートの平均計算量は O(n log n) 程度とされ、最悪の場合でもバブルソートの O(n²) よりも大幅に改善されることが多いです。ただし、理論上の最悪計算量は O(n²) のままなので、厳密な性能保証が必要な場面ではクイックソートなどの他のアルゴリズムとの使い分けを検討するとよいでしょう。
実装がシンプルで追加のメモリ領域がほぼ不要なため、組み込みシステムなどリソースが限られた環境でも扱いやすいソート手法といえます。
-
奇偶転置ソート(ブリックソート)をC/C++で実装する方法
奇偶転置ソート(ブリックソート)は、バブルソートとよく似たソートアルゴリズムの一つです。この手法は「奇数フェーズ」と「偶数フェーズ」の2つのフェーズから構成されており、すべての要素が整列されるまで、各反復ごとに両方のフェーズが交互に実行されます。奇数フェーズでは、バブルソートと同じ要領で比較と交換を行いますが、対象となるのは奇数番目のインデックスを持つ要素だけです。同様に、偶数フェーズでは偶数番目のインデックスを持つ要素のみが処理されます。概念をより分かりやすくするために、具体的な例を見てみましょう。入力:a[]={3,5,7,6,1,4,2} 出力:1 2 3 4 5 6 7アルゴリズムの解
-
二分法を用いて方程式の根を求めるC++プログラム
関数f(x)と2つの数a、bが与えられ、f(a)・f(b)<0を満たし、関数f(x)が区間[a, b]内に存在するとします。ここでの課題は、二分法(バイセクション法)を用いて、関数f(x)の区間aとbの間に存在する根の値を求めることです。 二分法とは? 二分法とは、「a」と「b」で定義された範囲内において、関数f(x)の根の値を求めるための数値計算手法の一つです。関数の根とは、その値を代入したときにf(x)=0となるような値xのことです。 例 方程式 F(x) = x^3 − 8 を考える この方程式は、x = 2 のとき F(x) = 2^3 − 8 = 0 となります。 したがって