ソート時間の比較

ここでは、今までに説明したソートアルゴリズムを比較してみましょう。

6種類のソートの比較アプレット

下のアプレットは、6種類すべてのソートアルゴリズムを同時に実行するものです。

左上から右へ、バブルソート、バケットソート、基数ソート、ヒープソート、マージソート、クイックソートです。

"Start" ボタンを押すと、すべてのソートが同時開始されます。クイックソートがもっとも速く並べ終わり、次にバケットソート、基数ソートの順で並べ終わるのがわかります。

データ数や初期並びを変えて、いろいろなデータで試してみましょう。

数値実験

アプレットの並べ替えプログラムは、人間の眼で見て並べ替えの様子がわかりやすいように、データの交換が起こるたびに wait を入れて速度を遅くして表示しています。しかし、この方法では、データの交換以外に要する時間はほとんど無視されることになり、正確な意味で正しい比較をしていることにはなりません。

そこで、wait を入れずに並べ替えを行うプログラムを作成し、いろいろな個数のデータを並べ替えてみて、その時間を測定しました。データは 1〜N の整数値で、初期状態ではランダムに並んでいます。

N を 100 から 100000 まで変化させて、100 回ずつ並べ替えを行った合計時間を、下のグラフに示します。参考までに、N log(N) と N*N のグラフも載せてあります。

wpe1.jpg (33054 バイト)

これを見ると、並べ替えに要する時間の増え方は、バブルソートでは N*N に平行になっており、そのほかのソートではほぼ N*log(N) に平行になっていることがわかります。これは、前章までで説明したように、バブルソートの並べ替えのオーダーは O(N2)、その他のソートのオーダーは O(N log(N)) であることを示しています。

次に、並べ替えの速度ですが、もっとも速いのはやはりクイックソートになっており、2番目がヒープソート、以下、バケットソート、マージソート、基数ソートの順で、最後がバブルソートです。

しかし、データが100個〜400個の範囲では、基数ソート、マージソートよりもバブルソートのほうが速いと言う結果が出ました。この理由は、基数ソートでは基数を10、桁数を3に固定して行っていますので、常にバケツに3回入れることになることが考えられます。実際、データ数が少ないときは3桁ものバケツを準備する必要はなく、いわば無駄な処理を行っていることになります。また、マージソートでは、配列を併合するために、new 演算子により新しい配列を生成していますので、このオーバーヘッドに要する時間が、アルゴリズム本来のデータの比較や入れ替えの時間遅れを上回った結果、本来遅いはずのバブルソートのほうが速いと言う結果が出たと言うわけです。

この結果は、基数ソートの桁数をデータに合うように調整する、あるいはマージソートでは配列をあらかじめ準備して、実行中に new を使わないようにする等の対策を講じることで、回避できると考えられます。

次のグラフは、ヒープソートの並べ替え時間を 1 としたときの、各ソートの時間の比を表したものです。

wpe3.jpg (29011 バイト)

平均すると、各ソートの速度比は次のようになります。

アルゴリズム 速度比
クイックソート 0.68
ヒープソート 1
バケットソート 1.26
マージソート 3.13
基数ソート 5.83
バブルソート 44.3
(ただし、最大は204倍)

バケットソートは、データ数の少ない場合にはクイックソートを上回る場合もありますが、データ数が増えてくると約2倍の時間がかかります。上のグラフを見ると、データ数が 500 〜 5000 にかけて、ヒープソトーの速度が上下しているように見えますが、実際はクイックソートに要する時間が大きく変動しています(最初のグラフを見ると分かる)。ヒープソートの特徴は、データのばらつき方の影響をあまり受けないで、安定した速度でソートできると言うことにあります。

バケットソートの並べ替え時間がかなり一定しないのは、原因不明です。理論的には、バケットソートもデータの初期状態に依然せず、安定した速度で並べ替えを行うはずです。誰か原因がわかったら、教えてください。

なお、実験に使用した環境は以下の通りです。

CPU Pentium II 300MHz
Memory 384MB
OS WindowsNT 4.0 SP3
Java JDK1.1.8

← prev | next →