K&RのANSI Cブックの再帰セクションでは、
クイックソートのバージョンは、可能な限り最速ではありませんが、最も簡単なバージョンの1つです。
--Cプログラミング言語(ANSI C)-pg。 87
全体として:
_/*qsort: sort v[left]...v[right] into increasing order*/
void qsort(int v[], int left, int right){
int i, last;
/*do nothing if array has less than 2 elements*/
if(left >= right)
return;
swap(v, left, (left + right) / 2);
last = left;
/*partition*/
for(i = left + 1; i <= right; i++)
if(v[i] < v[left])
swap(v, ++last, i);
swap(v, left, last); /*reset partition element*/
qsort(v, left, last - 1);
qsort(v, last + 1, right);
}
_
ここで、swap(v, i, j)
は、配列v
の2つのメンバーを交換します。
これがどのように配列をソートするのかを理解しようとしています。 last
は、配列を2つの小さな配列に分割し、左の境界要素と交換する配列要素のようです。次に、それは適切な境界までのすべての要素と比較され、各小さな要素が_++last
_に交換されます(なぜですか?)。
最後に、パーティション要素がスワップインされ、2つのサブ配列が個別にソートされます。
再帰を正しく理解している場合、このアルゴリズムは、1つのパスの終わりに、last
の左側にあるすべての要素がlast
の右側にあるすべての要素よりも小さいことを意味します。ほとんどのqsort
アルゴリズムはこれよりも複雑であるため、説明を見つけるのに苦労しています。
ここでのアルゴリズムは次のとおりです。
last
という名前)があります。小さい値が見つかるたびに、その値をインクリメントして、その値を置く場所を見つけます。この時点で、ピボットのどちらかの側にサブ配列があることがわかります。左側にはピボットより小さい値があり、右側にはピボット以上のすべての値があります。つまり、ピボットは、ソートされた最終的な配列の正確な場所にあることがわかります。また、どちらのサブ配列の値も、反対側の値と交換する必要がないことも知っています。だから今できる:
再帰するたびに、サブ配列が小さくなるため、次のレベルの再帰が速くなります。また、毎回、1つの要素を正しい位置に移動してから、さらに深く進みます。最終的には、サブ配列に要素が0または1つしかないポイントに到達します。これはもちろん、サブ配列がすでにソートされていることを意味します。任意のレベルで最終的に得られるのは、右側に小さい値の並べ替えられたサブ配列があり、右側に大きい値または等しい値の並べ替えられたサブ配列がある右側のスポットの要素です。そのレベルのサブ)配列がソートされます。