ソートのアルゴリズムにはいろいろありますが、中でもクイックソートは比較的高速なアルゴリズムです。その名前からも分かるように、qsort関数はクイックソートの実装であることを示唆しています。実際には、規格上はqsort関数にクイックソートを用いて実装することが要求されているわけではないので何でもよいのですが、多くの場合はクイックソートを用いていると考えられます。

標準Cライブラリでは、ソートのための関数はqsort関数しかないため、qsort関数は最も手軽に使用できるソート方法です。しかし、いくつかの状況では、qsort関数は使えませんし、使えたとしても好ましくありません。以下にqsort関数を使うべきでは状況を挙げてみます。

qsort関数が使えない状況

データ列が配列ではない場合

qsort関数はデータ列が配列であることを前提としています。線形リストであったり、ファイル上のデータであったりする場合には使えません。いったん配列に読み込んでからqsortでソートし、書き戻すことは可能ですが、多くの場合メリットがありません。マージソートなど、データ構造や格納方法に適した他の方法を用いてソートを自作する方がよいでしょう。なお、C++のstd::listの場合、メンバ関数sortを利用できます。

安定ソートが必要な場合

クイックソートは安定ではありません。すなわち、比較して値が等しい要素がどの順序になるかは不定です。比較して値が等しい要素が元の順序を保つ必要がある場合には不適切です。C++では、安定ソートにはstd::stable_sort関数テンプレートを利用することができます。

スタックが小さい場合

クイックソートは多くの場合、再帰呼出しを用いて実装されます。あるいは、再帰を用いない場合はあらかじめ大きな配列を自動変数として確保します。ローエンドの組込み機器など、スタックサイズの制限が厳しい環境では、ヒープソートなど、他の方法を選択する方が適しています。処理系がそのことを配慮してqsort関数を実装している場合は問題ありませんが、その場合でも移植を行う場合は要注意です。

フリースタンディング環境の場合

フリースタンディング環境ではqsort関数がサポートされません。処理系によっては提供されていることもありますが、移植性を考慮するなら使用すべきではないでしょう。

qsort 関数が好ましくない状況

計算時間を予測したい場合

リアルタイム性が要求される状況など、計算時間を予測したい場合には、データに依存して計算時間が大幅に変化するクイックソートは不向きです。クイックソートの計算時間は、平均的には\(O(n \log n)\)ですが、最悪計算時間は\(O(n^2)\)であり、これはバブルソートの計算時間と同じです。リアルタイム性を保証するには、最悪計算時間に合わせるしかないため、クイックソートの利用は好ましくありません。ヒープソートなどを用いて自作すべきでしょう。

C++の場合

C++では、実装にもよりますが、qsort関数よりstd::sort関数テンプレートを用いる方が圧倒的に高速です。qsortは比較関数のコールバックがかなり大きなオーバーヘッドになります。一方、C++のstd::sortでは、比較に関数オブジェクトを使えますので、結果としてインライン置換することが可能になります。

また、配列の要素がC互換型(POD型)であればよいのですが、そうでなければ、qsort関数を使うと不具合につながります。なぜなら、qsort関数では、要素の交換を単なるメモリブロックの交換として行っているだけであり、適切なswap関数を用いたり、コピーコンストラクタを呼び出したり、といったことは一切ないからです。

実は、今回「データ列のソートには qsort 関数を使うべし」を迷信として採り上げたのは、 C++の場合に関しての理解不足をよく見かけるからです。先に挙げた(C++以外の)状況でqsort関数を使うべきでないことは、少し経験を積んだプログラマであれば容易に判断がつきます。しかし、単にC++になっただけの場合には、ついstd::sortではなくqsortを使ってしまうものです。