ソートを実行するCライブラリ関数


96

ソートを行うためにC標準ライブラリで使用可能なライブラリ関数はありますか?


21
@ Alexandru、SOのすべてのポイントは、あらゆるスキルレベルのプログラミング関連のすべての質問の場所になることです。あなたのクエリを使用するときに、Googleはどこに人々を向けるべきだと思いますか?ここに来ることを望む力-SOがそのクエリの最上位のGoogleリンクであるとき、私たちの仕事は終わりです。
paxdiablo 2009年

1
私の元のコードは怠惰で、おそらくGoogle検索で見つけたものとはかなり異なっていました。しかし、すべてのコミュニティーの入力の後に、qsortの使用方法の適切な実装の例があります。
再実行

@paxdiablo:その場合は、単に標準のlibドキュメントをホストするだけかもしれません-この質問で、ここでの正規の参照より上に何かが追加されることはないと思います。いくつかの複雑なケースでは、おそらく-基本的な機能を見つけるだけですか?
Eamon Nerbonne、2009年

4
このような質問でさえ、行き詰まったコーダーにとって有用なデータベースとして、SOの最終的な完成に貢献します。
thomaspaulb 2010年

7
また、多くの場合、人々は何を検索すればいいのかわかりません。cにqsort()という名前のソート関数があることがわかっていれば、ドキュメントに簡単にアクセスできますが、どのリソースを探すべきかわからない場合は、ドキュメントに簡単にアクセスできます。
2010年

回答:


119

qsort()あなたが探している機能です。データの配列へのポインタ、その配列内の要素の数、各要素のサイズ、および比較関数を使用して呼び出します。

それはその魔法を行い、あなたの配列はその場でソートされます。次に例を示します。

#include <stdio.h>
#include <stdlib.h>
int comp (const void * elem1, const void * elem2) 
{
    int f = *((int*)elem1);
    int s = *((int*)elem2);
    if (f > s) return  1;
    if (f < s) return -1;
    return 0;
}
int main(int argc, char* argv[]) 
{
    int x[] = {4,5,2,3,1,0,9,8,6,7};

    qsort (x, sizeof(x)/sizeof(*x), sizeof(*x), comp);

    for (int i = 0 ; i < 10 ; i++)
        printf ("%d ", x[i]);

    return 0;
}

3
将来タイプを変更する場合に備えて、実際にはsizeof(* x)を使用する必要がありますが、サンプルを提供するために+1を使用してください。
paxdiablo 2009年

12
一般に、intを別の整数から減算して比較しようとすると、オーバーフローが発生します。最初からその悪い習慣に近づかないほうがいいです。使用return (f > s) - (f < s);
ANT

4
さて、ほとんどの提案に従って変更されました。私の配列はそれほど大きくならないので、私はsize_tを必要とするときに@ChrisLと線を引きます:-)そして、@ AndreyT、そのハックは賢いですが、私のコードは読みやすくすることを好みます:-)
paxdiablo

2
@paxdiablo:その「ハック」は定評のあるイディオムです。彼の才能に値するプログラマは誰でもすぐにそれを認識します。読みやすさに悪影響はありません。
AnT 2009年

2
@JAamish ISO C99標準N1256、「7.20.5.2 qsort関数」ポイント4「2つの要素が等しいと比較される場合、結果のソートされた配列での順序は指定されていません。」
12431234123412341234123 2018年

60

C / C ++標準ライブラリに<stdlib.h>qsort関数が含まれています。

これは世界で最も速いクイックソートの実装ではありませんが、十分に速く、非常に簡単に使用できます... qsortの正式な構文は次のとおりです。

qsort(<arrayname>,<size>,sizeof(<elementsize>),compare_function);

実装する必要があるのは、compare_functionだけです。この関数は、「const void」型の2つの引数を取り、適切なデータ構造にキャストして、次の3つの値のいずれかを返します。

  • 負、aがbの前にある場合
  • 0、aがbと等しい場合
  • aがbの後にある場合は正

1.整数のリストを比較する

単にあれば整数にaとbをキャストしx < yx-y負である、x == yx-y = 0x > yx-y正がされ x-y、それが逆に:)実行するショートカットの方法である*x - *y*y - *x減少/逆順にソートするために

int compare_function(const void *a,const void *b) {
int *x = (int *) a;
int *y = (int *) b;
return *x - *y;
}

2.文字列のリストを比較する

文字列を比較するには、lib strcmp内に関数が必要<string.h>です。 strcmpデフォルトでは-ve、0、veを適切に返します...逆順にソートするには、strcmpによって返される符号を逆にします

#include <string.h>
int compare_function(const void *a,const void *b) {
return (strcmp((char *)a,(char *)b));
}

3.浮動小数点数の比較

int compare_function(const void *a,const void *b) {
double *x = (double *) a;
double *y = (double *) b;
// return *x - *y; // this is WRONG...
if (*x < *y) return -1;
else if (*x > *y) return 1; return 0;
}

4.キーに基づくレコードの比較

レコードなど、より複雑なものをソートする必要がある場合があります。これは、qsortライブラリーを使用して行う最も簡単な方法です。

typedef struct {
int key;
double value;
} the_record;

int compare_function(const void *a,const void *b) {
the_record *x = (the_record *) a;
the_record *y = (the_record *) b;
return x->key - y->key;
}

2
かなり良い答えですが、比較関数の戻り値の説明は逆です。また、一部の例では、xyトリックを実行していますが、これは誤った結果をもたらす可能性があります(単純な比較ほど明白ではありません)。
エイドリアン・マッカーシー、

ええと、私が今懸念している限り、これはすべてのコンテストで機能します;)
whacko__Cracko '24年

5
xとyの差が表現可能な最大のintより大きい場合、xyトリックは機能しません。したがって、2つの正の数を比較する場合は問題ありませんが、INT_MAXと-10などの比較は失敗します。ただし、非常に異なるタイプをソートするすべての例が好きなので、賛成です。
ダグラス

2
整数コンパレーター関数とキーコンパレーター関数のオーバーフローの問題と同様に、文字列比較関数は正しくありません。の配列をソートする場合int、コンパレータに渡される値は両方ともにint *偽装されvoid *ます。char *したがって、の配列をソートする場合、コンパレータに渡される値は両方ともにchar **偽装されvoid *ます。したがって、正しいコードは次のようにする必要がありますint compare_function(const void *a,const void *b) { return (strcmp(*(char **)a, *(char **)b)); }
Jonathan Leffler 2017年

1
オーバーフローに強い整数比較の場合は、を検討if (x > y) return +1; else if (x < y) return -1; else return 0;するか、単純な式が必要な場合はを検討してくださいreturn (x > y) - (x < y);。これは常にCレベルで2つの比較を評価しますが、オプティマイザはそれを回避できる可能性があります。減算は、符号なしの値では機能しません。最初のバージョンは、一連の比較を処理しているときにうまく機能します。最初に構造体の2つの整数メンバーを比較し、それらが等しい場合は2つのdouble、次に2つの文字列などです。これを行う方法は複数ありますが、 CおよびPerl。
Jonathan Leffler 2017年


6

標準ライブラリには正確にはありませんが、https://github.com/swenson/sortには、次のように、信じられないほど高速な幅広いソートルーティングにアクセスするために含めることができる2つのヘッダーファイルがあります。

#define SORT_NAME int64 #define SORT_TYPE int64_t #define SORT_CMP x y ((x - y ))#include "sort.h" / *これで、int64_quick_sort、int64_tim_sortなどにアクセスできます。
int64_quick_sort arr 128 ); / *いくつかのint * arrまたはint arr [128]があると想定します。* /

   
 
  

これはqsort、関数ポインターを使用しないため、標準ライブラリーの少なくとも2倍の速さである必要があり、その他の多くのソートアルゴリズムオプションから選択できます。

それはC89にあるので、基本的にすべてのCコンパイラで動作するはずです。



4

で使用qsort()<stdlib.h>ます。

@paxdiablo qsort()関数はISO / IEC 9899:1990(「ISO C90」)に準拠しています。


3

には、いくつかのCソート関数がありますstdlib.h。あなたman 3 qsortはそれらのリストを取得するためにUNIXマシンで行うことができますが、それらには以下が含まれます:

  • ヒープソート
  • クイックソート
  • マージソート

7
heapsortとmergesortは標準にはありません。
Technowise、2009年

3
どちらもクイックソートではありません。標準では、どのアルゴリズムを使用するかは規定されていません。
paxdiablo 2009年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.