C++でシェーカーソートを実装する方法|アルゴリズムとサンプルコード解説
シェーカーソートとは
シェーカーソート(Shaker Sort)は、与えられたデータを昇順に並べ替えるためのソートアルゴリズムの一つです。バブルソートとよく似ていますが、決定的に異なるのは配列を双方向(往復)に走査して整列を進める点です。「カクテルソート」「双方向バブルソート」と呼ばれることもあります。このアルゴリズムの最悪計算量は O(n²) です。
アルゴリズムの手順
開始 ShakerSort() 関数は、引数としてデータ配列 arr と要素数 n を受け取る。 // ネストした for ループを使ってソートを実装する。 外側のループは i を 0 から n-1 まで回し、内部に2つのループを持つ。 1つ目のループは j を i+1 から n-1 まで回し、a[j] < a[j-1] なら swap() で隣接要素を交換する。 n をデクリメントする。 2つ目のループは k を m-1 から i+1 まで回し、a[k] < a[k-1] なら swap() で隣接要素を交換する。 i をインクリメントする。 終了
具体的には、まず左から右へ走査して大きな値を末尾側へ移動させ、続いて右から左へ走査して小さな値を先頭側へ移動させます。未整列の範囲を両端から狭めながらこれを繰り返すことで、配列全体が整列されます。
C++によるサンプルコード
#include<iostream>
using namespace std;
void swap(int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void ShakerSort(int a[], int m) {
int i, j, k;
for(i = 0; i < m;) {
// 前方向のパス:大きい値を後ろへ移動
for(j = i+1; j < m; j++) {
if(a[j] < a[j-1])
swap(&a[j], &a[j-1]);
}
m--;
// 後方向のパス:小さい値を前へ移動
for(k = m-1; k > i; k--) {
if(a[k] < a[k-1])
swap(&a[k], &a[k-1]);
}
i++;
}
}
int main() {
int n, i;
cout<<"\nソートするデータ要素の個数を入力してください: ";
cin>>n;
int a[n];
for(i = 0; i < n; i++) {
cout<<"要素 "<<i+1<<" を入力: ";
cin>>a[i];
}
ShakerSort(a, n);
cout<<"\nソート後のデータ ";
for (i = 0; i < n; i++)
cout<<"->"<<a[i];
return 0;
}
補足: 上記のコードで使われている可変長配列(int a[n];)はGCCなど独自拡張の機能であり、標準C++の規格では保証されていません。移植性を重視する場合は、std::vector<int> の利用を推奨します。
実行結果
ソートするデータ要素の個数を入力してください: 4 要素 1 を入力: 3 要素 2 を入力: 1 要素 3 を入力: 7 要素 4 を入力: 6 ソート後のデータ ->1->3->6->7
まとめ
シェーカーソートは、バブルソートを双方向化することで、配列の後方にある小さな要素を素早く先頭側へ移動できるようにした改良版ソートです。計算量は平均・最悪ともに O(n²) と大規模データには不向きですが、仕組みがシンプルで直感的に理解しやすいため、ソートアルゴリズムの学習用として最適な題材といえます。
-
C++で均一二分探索(一様二分探索)を実装する方法とサンプルコード
均一二分探索では、あらかじめ作成しておいたルックアップテーブルを使って二分探索を実装します。シフト演算と加算を繰り返す従来の二分探索に比べ、テーブル参照のほうが高速に行えるため、二分探索の改良版と位置づけられています。この手法の時間計算量は O(log n) です。 均一二分探索の仕組み ポイントとなるのは、配列長 n に対して「n/2, n/4, n/8, …」という差分(デルタ)を格納したテーブルです。探索は必ず配列のほぼ中央から始まり、キーが現在の要素より小さければテーブルの次の差分だけ左へ、大きければ右へ移動します。これにより、ループ内での除算やシフト計算を省き、単純な加減算とテーブル
-
C++でストゥージソートを実装する方法:再帰的ソートアルゴリズムの解説とサンプルコード
ストゥージソート(Stooge Sort)は、与えられたデータを並べ替えるための再帰的なソートアルゴリズムです。配列をそれぞれ全体の2/3ずつが重なり合う2つの部分に分割し、「前半部分のソート → 後半部分のソート → 再び前半部分のソート」という3段階の手順で整列を行います。このアルゴリズムの最悪計算量は O(n^2.7095) であり、バブルソート(O(n²))よりも遅いという特徴があります。実用性は低いものの、再帰処理やアルゴリズムの学習教材として知られています。アルゴリズムの手順Begin データを入力として受け取る。 データ配列 a と要素数 n を引数として Stoog