2011-10-19
quick sortよりも高速でmerge sortのように安定しているソートアルゴリズムtim sort [勘違い]
<追記>ベンチマークプログラムに誤りがありました。ソート済のシーケンスに対してソートを掛けていました。ご指摘ありがとうございます>ak氏</追記>
そんな夢のようなソートアルゴリズムがあるのかというと、あるらしいんです。それがtim sortと呼ばれるアルゴリズムです。
濃縮還元オレンジニュース:画期的(?)なソートアルゴリズム「Sleep Sort」|gihyo.jp … 技術評論社
このあたりで拾ってきたネタですね。
merge sortを改良したアルゴリズムで、安定*1しており、しかも実行速度にも優れているとか。アルゴリズムの性能の評価は済んでいるらしく、CPythonやJDK7には既に導入済みのようですね。
ならば当然Perlのソートも…と考えるわけですが、まず評価のためにJavaのソースをC++にそのまま移植してみました。それがこれ(いちおうテスト済):
https://github.com/gfx/cpp-TimSort/blob/master/timsort.hpp
オリジナルはこちら:
インターフェイスはC++の標準ライブラリstd::sort()/std::stable_sort()と同じです。
int/double/boost::rational<long long>の入ったstd::vectorをランダムシャッフルしてソートする、というベンチマークだと結果は以下のようになりました。
https://github.com/gfx/cpp-TimSort/blob/master/bench.cpp
# MacOSX Snow Leopard / Apple clang 2.0 (llvm 2.9)
$ clang++ -DNDEBUG -O2 -Wall -Wextra bench.cp -o bench
$ ./bench
int
size 100000
std::sort 0.12273
std::stable_sort 0.182555
timsort 0.021382
double
size 100000
std::sort 0.121308
std::stable_sort 0.221106
timsort 0.026283
boost::rational
size 100000
std::sort 3.60624
std::stable_sort 2.60706
timsort 0.319079</del>
適当なベンチマークですがだいぶ高速ですね。以下の記事では、ランダムなデータだとmerge sortよりも劣るという結果ですが、こちらはC++なせいかそうでもないように見えます。
Java 7のArrays.sort(Object[]):柴田 芳樹 (Yoshiki Shibata):So-netブログ
このアルゴリズム、かなり複雑なのでソラで書けそうもないのが欠点ですが、これだけ高速ならPerlに移植する価値はありそうです。
ベンチマークプログラムが誤っていたので再検討中...取り急ぎ修正してみると特に高速ではありません: https://github.com/gfx/cpp-TimSort/commit/392af11ea2dea47a93b705a5ef95994449766113
*1:この「安定(stable)」はソートアルゴリズムの用語で、同等のデータのソート前の並び順が、ソート後も保持されるという意味です。テストコードで示すと次のtest.cppのstabilityテストのような挙動を示すものです。 https://github.com/gfx/cpp-TimSort/blob/master/test.cpp#L157
購入: 27人 クリック: 853回
- 718 http://reader.livedoor.com/reader/
- 647 http://b.hatena.ne.jp/hotentry/it
- 625 http://b.hatena.ne.jp/hotentry
- 412 http://t.co/LXrGXFgT
- 372 http://t.co/Ku4sbDm5
- 295 http://t.co/pI7njhkn
- 279 http://pipes.yahoo.com/pipes/pipe.info?_id=04913f684f1141e0b48179f97811ce12
- 235 http://bit.ly/ogW8MP
- 209 http://www.google.co.jp/reader/view/
- 188 http://longurl.org


