マルチキー・クイックソート(multikey-quicksort)で高速に文字列ソート
一般にソートアルゴリズムの計算量はソート対象となるデータ数NについてO(N^2)とかO(NlogN)等で評価する。数値データのソートであれば特に問題はないのだが、文字列データの場合は一回の比較に対して文字列長Mに比例する計算量O(M)がかかってしまう。例えばクイックソートであればO(NlogN)ではなくO(MNlogN)となる。よってMが非常に大きい場合はソート性能の劣化を招く。
文字列ソートに付いてはBently&Sedgewickのマルチキー・クイックソート(multikey-quicksort)という改良版クイックソートが存在する。このソート法は、ある工夫によって一回の比較を文字列長Mに依存しない形で実現している。
例えば文字列appleとapplicationの比較について考える。
# 先頭の文字を比較 [a]pple = [a]pplication # 2文字目を比較 a[p]ple = a[p]plication # 3文字目を比較 ap[p]le = ap[p]lication # 4文字目を比較 app[l]e = app[l]ication # 5文字目を比較 appl[e] < appl[i]cation # apple < applicationとなる
といった感じで、先頭の文字から順番に比較していきイコールじゃなくなった時点で大小関係が決まる。ということは最初の文字比較でイコールでなければ直ぐに大小関係が決まる。この性質をマルチキー・クイックソートでは使っている。
普通のクイックソートではピボットとして適当な(例えば真ん中の)データを選び、そのデータより大きいグループ、小さいグループに分ける。これに対してマルチキー・クイックソートはピボットとなるデータに対して比較するときに先頭の一文字しか比較しない。その代わりピボットより小さいグループ、大きいグループ、同じグループの3つに分ける。
どういうことかというと、
change dog cat apple bag egg
というデータをソートするときにピボットをまず選び(今回はcatにする)、ピボットの先頭一文字をキーとして小、大、同じのグループに分ける
[小] [b]ag [a]pple [同じ] [c]hange [c]at [大] [d]og [e]gg
ここで、各々のグループに対して再帰的にソートをする。ただし[同じ]グループは先頭文字が同じであることが分かっているので、比較文字を2文字目にする。つまり
[小] [b]ag [a]pple [同じ] c[h]ange c[a]t [大] [d]og [e]gg
で[]のついている文字で各グループがマルチキー・クイックソートをする。結果、
[小] [a]pple [b]ag [同じ] c[a]t c[h]ange [大] [d]og [e]gg
というようになる。各々の比較では文字同士の比較しかしていないので文字列長Mに対して計算量がO(1)となるところがポイント。
参考:
Fast Algorithm for Sorting and Searching Strings J. L. Bentley & R. Sedgewick, 1997