정렬을 수행하는 C 라이브러리 함수


98

C 표준 라이브러리에서 정렬을 수행 할 수있는 라이브러리 기능이 있습니까?


21
@Alexandru, SO의 요점 은 모든 기술 수준 의 모든 프로그래밍 관련 질문을 위한 장소가되는 것 입니다. 사람들이 귀하의 검색어를 사용할 때 Google이 사람들을 어디로 안내해야한다고 생각하십니까? 여기 에 오기를 원하는 힘 -SO가 해당 쿼리에 대한 최상위 Google 링크 일 때 우리의 작업이 완료됩니다.
paxdiablo

1
내 원래 코드는 게으르고 아마도 Google 검색에서 찾은 것과 많이 다를 것입니다. 그러나 모든 커뮤니티 입력 후에 qsort를 사용하는 방법에 대한 좋은 구현 예가 있습니다.
다시 실행

@paxdiablo : 그렇다면 표준 lib 문서를 호스팅하는 것이 좋을 것입니다.이 질문이 여기에 표준 참조 위에 무엇이든 추가 할 것 같지 않습니다. 일부 복잡한 경우에는 아마도-기본 기능을 찾기 위해?
Eamon Nerbonne

4
이와 같은 질문조차도 고착 된 코더를위한 유용한 데이터베이스로서 SO의 궁극적 인 완성도에 기여합니다.
littlegreen 2010-01-22

7
또한 많은 경우에 사람들은 무엇을 검색해야할지 모릅니다. c에 qsort ()라는 정렬 함수가 있다는 것을 알고 있다면 문서에 쉽게 액세스 할 수 있지만 어떤 리소스를 사용해야하는지 알 수없는 경우.
재실행

답변:


120

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

12
일반적으로 int를 다른 것에서 빼서 비교하려고하면 오버플로가 발생합니다. 처음부터 나쁜 습관을 피하는 것이 좋습니다. 사용return (f > s) - (f < s);
AnT

4
좋습니다. 대부분의 제안에 따라 변경되었습니다. 그 해킹은하지만, 내가 읽을 수 내 코드를 :-) 선호 영리 @AndreyT을 내 배열은 그 큰를 :-) 결코 때문에이 size_t를 필요에서, 라인, @ChrisL을 그리고
paxdiablo

2
@paxdiablo : "해킹"은 잘 정립 된 관용구입니다. 그의 소금 가치가있는 프로그래머는 즉시 그것을 인식합니다. 가독성에 부정적인 영향을 미치지 않습니다.
AnT

2
@JAamish ISO C99 Standard N1256, "7.20.5.2 qsort기능"포인트 4 "두 요소가 동일한 것으로 비교되면 결과 정렬 된 배열의 순서가 지정되지 않습니다."
12431234123412341234123

61

C / C ++ 표준 라이브러리 <stdlib.h>에는 qsort함수 가 포함되어 있습니다.

이것은 세계 최고의 빠른 정렬 구현은 아니지만 충분히 빠르고 사용하기 매우 쉽습니다 .qsort의 공식 구문은 다음과 같습니다.

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

구현해야하는 유일한 것은 compare_function입니다. 이는 "const void"유형의 두 인수를 취하고 적절한 데이터 구조로 캐스트 될 수 있으며 다음 세 값 중 하나를 반환합니다.

  • 음수, a가 b 앞에 있어야하는 경우
  • a가 b와 같으면 0
  • 양수, a가 b 뒤에 있어야하는 경우

1. 정수 목록 비교 :

단순히 경우 정수 a와 b 캐스팅 x < y, x-y부정적이다 x == y, x-y = 0, x > y, x-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 트릭을 수행하고 있습니다 (간단한 비교보다 명확하지 않음).
Adrian McCarthy

글쎄, 내가 지금 염려하는 한 .. 이것은 모든 콘테스트에서 작동합니다;)
whacko__Cracko

5
x와 y의 차이가 표현 가능한 가장 큰 int보다 크면 xy 트릭이 작동하지 않습니다. 따라서 두 개의 양수를 비교할 때는 괜찮지 만 INT_MAX와 -10과 같이 비교는 실패합니다. 나는 매우 다른 유형을 정렬하는 모든 예를 좋아하기 때문에 찬성했습니다.
Douglas

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 개를 비교하고 같으면 두 개의 double, 두 개의 문자열 등을 비교합니다.이를 수행하는 방법은 여러 가지가 있습니다. C와 Perl에서.
Jonathan Leffler 2017


6

표준 라이브러리에 정확히 포함되어 있지는 않지만 https://github.com/swenson/sort 에는 다음과 같이 광범위한 엄청나게 빠른 정렬 라우팅에 액세스하기 위해 포함 할 수있는 두 개의 헤더 파일 만 있습니다.

#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그들을 나열하지만이 포함 얻을 수있는 유닉스 시스템에서 :

  • 힙 정렬
  • 퀵 정렬
  • 병합 정렬

7
heapsort 및 mergesort는 표준에 없습니다.
Technowise

3
둘 다 퀵 정렬도 아닙니다. 표준은 어떤 알고리즘이 사용되는지를 요구하지 않습니다.
paxdiablo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.