クイックソート
出典: フリー百科事典『ウィキペディア(Wikipedia)』
クイックソートは、1960年にアントニー・ホーアが開発したソートのアルゴリズム。分割統治法の一種。
最良計算量および平均計算量はO(nlogn)である。他のソート法と比べて、一般的に最も高速だといわれているが対象のデータの並びやデータの数によっては必ずしも速いわけではなく、最悪の計算量はO(n2)である。また数々の変種がある。 安定ソートではない。
[編集] アルゴリズム
- 適当な数(ピボットという)を選択する (データの中央値が望ましい)
- ピボットより小さい数を前方、大きい数を後方に移動させる (分割)
- 二分割された各々のデータを、それぞれソートする
実際にこれを実現するためのアルゴリズムは色々考えられるが、一例を挙げると以下のようなものがある。
- ピボットとして一つ選びそれをPとする。
- 左から順に値を調べ、P以上のものを見つけたらその位置をiとする。
- 右から順に値を調べ、P以下のものを見つけたらその位置をjとする。
- iがjより左にあるのならばその二つの位置を入れ替え、2に戻る。ただし、次の2での探索はiの一つ右、次の3での探索はjの一つ左から行う。
- 2に戻らなかった場合、iの左側を境界に分割を行って2つの領域に分け、そのそれぞれに対して再帰的に1からの手順を行う。要素数が1以下の領域ができた場合、その領域は確定とする。
注:このアルゴリズムでは、領域の左端の値が領域内で最小かつ同じ値が他の位置に無い場合、ピボットとしてその値を選ぶとループとなってしまう。
ピボットは、通常、データ列からランダムに選んだり、データ列中の適当な三つ程度の数の中央値を選ぶ。このように、ピボットの選び方を工夫することで、最悪計算時間がかかってしまうような入力データ列の可能性を抑える。
また、再帰的にソートする際、対象となるデータの数が少なくなったら、挿入ソートなどの別のアルゴリズムを適用することで高速化する手法が研究されている。
[編集] アルゴリズムの動作例
確定した部分は太文字で表す。ピボットには下線を引く。
初期データ: 8 4 3 7 6 5 2 1
- 中央付近に位置する7をピボットとする。左から7以上を探索して8を発見。右から7以下を探索して1を発見。前者が左にあるため入れ替え。
- 1 4 3 7 6 5 2 8
- 次の位置から探索を継続。7と2を発見して入れ替え。
- 1 4 3 2 6 5 7 8
- 次の位置から探索を継続。7と5を発見。前者が右にあるため探索終了。左からの探索で最後に発見した位置(7の位置)の左で分割。
- 1 4 3 2 6 5 | 7 8
- 「1 4 3 2 6 5」の領域で2をピボットとして探索。左からの探索で4、右からの探索で2を発見、前者が左にあるため入れ替え。
- 1 2 3 4 6 5 | 7 8
- 次の位置から探索を継続。3と2を発見。前者が右にあるため探索終了。3の左で分割。
- 1 2 | 3 4 6 5 | 7 8
- 「1 2」の領域を2をピボットとして探索、双方とも2を発見、同じ位置であるため探索終了。2の左で分割。「1」「2」の領域は確定。
- 1 | 2 | 3 4 6 5 | 7 8
- 「3 4 6 5」の領域を6をピボットとして探索。6と5を発見、前者が左にあるため入れ替え。
- 1 | 2 | 3 4 5 6 | 7 8
- 次の位置から探索を継続。6と5を発見するが前者が右にあるため探索終了。6の左で分割。「6」は確定。
- 1 | 2 | 3 4 5 | 6 | 7 8
- 「3 4 5」の領域を4をピボットとして探索。双方4を発見して終了するため4の左で分割。「3」は確定。
- 1 | 2 | 3 | 4 5 | 6 | 7 8
- 「4 5」の領域を5をピボットとして探索。双方5を発見して終了するため5の左で分割。「4」「5」は確定
- 1 | 2 | 3 | 4 | 5 | 6 | 7 8
- 「7 8」の領域を8をピボットとして探索。双方8を発見して終了するため8の左で分割。すべて確定。
- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8