joseph415   5년 전

저가 라이브러리에 있는 qsort 쓰면서 compare 함수를 생각없이 만들어 쓰다가  갑자기 리턴값에 대해 의문이 들어서 질문드립니다.

아래 코드 compare1,2,3 보면 리턴값이 다다르잖아요 

저는 원래 스트링컴페어에서 크면 1 작으면 -1 값으면 0 이런식으로 해서 리턴값을 섰는데 

compare2 에서 보면 리턴값을 저런식으로 해도 소팅 이 되더라구요 즉 ,그냥 리턴값만 다르게 해주니까 알아서 소팅이 되던데 

컴페어 함수에서 쓰이는 리턴값은 뭘의미 하는건가요?? ㅠ

bupjae   5년 전

결론부터 말하자면 저 세 함수 모두 잘못된 구현입니다.


qsort 의 네 번째 인자로 주어지는 함수 int (*func)(const void * a, const void *b) 는 다음과 같이 행동해야 합니다.

* 정렬했을 때 a가 b보다 더 뒤에 있어야 한다면 0보다 큰 수를 반환해야 한다

* 정렬했을 때 a가 b보다 더 앞에 있어야 한다면 0보다 작은 수를 반환해야 한다

* 정렬했을 때 a와 b가 동등하다면 0을 반환해야 한다.


특히, 비교함수는 다음과 같은 성질을 따라야 합니다.

* func(a, a) = 0

* sign(func(a, b)) + sign(func(b, a)) = 0

* qsort 함수가 동작하는 동안 sign(func(a, b))의 결과값은 consistent 할 것


저 세 함수는 공통적으로 두 번째 조건을 어기고 있습니다.

이렇게 되면 정렬 결과는 아무도 알 수 없게 됩니다.

특정 구현체에서 특정 데이터를 넣었을 때 정렬이 잘 되는 것 처럼 보여도, 데이터가 조금만 달라거나 구현체가 달라지면 전혀 엉뚱한 결과를 낼 수 있습니다.

제가 저 세 함수를 직접 테스트 해 본 결과, gcc 및 clang 에서는 정렬이 제대로 되었지만, Visual C++ 에서는 정렬이 제대로 이루어지지 않았습니다.


올바른 정렬 함수를 밑에 첨부하겠습니다. gcc, clang 및 VC++ 모두 제대로 정렬되는 것을 확인했습니다.

joseph415   5년 전

와 정말 감사합니다 

이거때문에 나이순으로 정렬 하기 문제에서 계속 이상한 값이 나와서 뭐가 잘못된지 못찾고있었는데. 

정말 감사합니다. 소트 컴페어 함수에대해 정말 명확하게 알아값니다.

joseph415   5년 전

@bupjae 님 질문이있습니다.


혹시 아래 코드 보면 컴페어 함수 댓글다신거처럼 바꿔서 표현했는데 clion에서 잘 나오던데 

백준에서 런타임 에러 뜨더라고요 혹시 이것도 잘못짠 코드인가요??

댓글을 작성하려면 로그인해야 합니다.