50
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

差分ソートアルゴリズム「刹那式」の紹介(ベンチマークあり)

Last updated at Posted at 2019-03-23

刹那式

刹那式(せつなしき)は、二分挿入ソートを応用した、差分ソートです。
ソート済み配列に対し、値の変更を行った箇所に焦点を当て、超高速にソートします。

以下の特徴があります。

  • 比較ソート
  • 安定ソート
  • 外部領域:無し
  • 平均時間:比較O(log N)、移動O(N/2)
  • 最悪時間:比較O(log N)、移動O(N)
  • 最良時間:比較O(2)、移動O(0)
  • 再帰:無し

リポジトリ

刹那式(せつなしき) Unlicense

基本となるアルゴリズム

  • ソート済み配列に対して、任意の位置の値を変更します。
  • (変更位置の値 < 変更位置の下の値)であれば、下方を二分探索し、変更位置から探索位置を回転します。
  • (変更位置の上の値 < 変更位置の値)であれば、上方を二分探索し、変更位置から探索位置を回転します。

具体的な流れ

ソート済み配列に対して、任意の位置の値を変更します
0 1 2 4 5 6 7 9|ソート済み配列
        ↓
0 1 2 4 x 6 7 9|任意の位置の値を変更
(変更位置の値 < 変更位置の下の値)であれば、下方を二分探索し、変更位置から探索位置を回転します
0 1 2 4 5 3 7 9|[5]=3の場合
0 1 2 4 5|. . .|下方を二分探索
. . .|3 4 5|. .|変更位置から探索位置を回転
0 1 2 3 4 5 7 9|ソート結果
(変更位置の上の値 < 変更位置の値)であれば、上方を二分探索し、変更位置から探索位置を回転します
0 1 8 4 5 6 7 9|[2]=8の場合
. . .|4 5 6 7 9|上方を二分探索
. .|4 5 6 7 8|.|変更位置から探索位置を回転
0 1 4 5 6 7 8 9|ソート結果

ビルド&テスト

環境は以下のとおりです。

  • Windows 10 Pro 64bit
  • Core i7-8700 3.20GHz

Msvc

Microsoft(R) C/C++ Optimizing Compiler Version 19.15.26732.1 for x64
Microsoft (R) Incremental Linker Version 14.15.26732.1

cl Main.cpp -Ox -EHsc -Fe:TestMsvc.exe
TestMsvc.exe

clang++

clang version 7.0.0 (tags/RELEASE_700/final)
Target: x86_64-w64-windows-gnu

clang++ Main.cpp -O3 -o TestClang++.exe
TestClang++.exe

g++

gcc version 8.2.0 (Rev3, Built by MSYS2 project)
Target: x86_64-w64-mingw32

g++ Main.cpp -O3 -o TestG++.exe
TestG++.exe

平均ベンチマーク

以下は、ソート済み配列に対し、ランダムな位置を、ランダムな値に変更した場合です。
単位は秒で、数値が低いほど高速です。

Msvc

件数 std::sort std::stable_sort 刹那式
10,000 0.00007095 0.00004502 0.00000115
1,000,000 0.00975892 0.00698905 0.00009487
100,000,000 0.27018098 1.26169269 0.01670523

clang++

件数 std::sort std::stable_sort 刹那式
10,000 0.00006162 0.00006669 0.00000050
1,000,000 0.00775640 0.00978430 0.00006938
100,000,000 0.99487866 1.46673092 0.01248609

g++

件数 std::sort std::stable_sort 刹那式
10,000 0.00009420 0.00006123 0.00000040
1,000,000 0.01269281 0.00870394 0.00006129
100,000,000 1.32669707 1.32506381 0.01232715

特性ベンチマーク

以下は全て、「100,000,000」件でソートしました。
単位は秒で、数値が低いほど高速です。

最悪ケース1

ソート済み配列に対し、先頭を最大値に変更した場合です。

std::sort std::stable_sort 刹那式
Msvc 0.28328255 1.27838705 0.03301556
clang++ 0.94680632 1.49072315 0.02450915
g++ 1.24406811 1.35104790 0.02465655

最悪ケース2

ソート済み配列に対し、末尾を最小値に変更した場合です。

std::sort std::stable_sort 刹那式
Msvc 0.29024827 1.27097092 0.03784692
clang++ 6.59369224 1.44779880 0.02844831
g++ 7.05050788 1.30785120 0.02579642

最良ケース

ソート済み配列に対し、値を変更せずに、位置をランダムにした場合です。

std::sort std::stable_sort 刹那式
Msvc 0.26143167 1.24644350 0.00000026
clang++ 0.99570890 1.44735863 0.00000031
g++ 1.33114203 1.30589223 0.00000050

余談

如何だったでしょうか?

ソートは、常に全体で行う必要はないという観点から、差分ソートという考えに至ったアイデアです。
本来であれば、全体ソートである std::sort と std::stable_sort との比較はフェアではないのですが、差分ソートの有用性を判断していただくには必要かと思い、ベンチマークを掲載することにしました。
参考になれば幸いです。

上手く運用すれば、激速なパフォーマンスが得られますが、使い方を誤ると激遅になる諸刃の剣。

ソートアルゴリズムには、まだ浪漫が残っています。


以下の記事も併せて読んでいただけると、より楽しめるかも知れません。

50
18
11

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
50
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?