qsort(3)

#include <stdlib.h>

void qsort(void *base, size_t nmemb, size_t size,  int (*compar)(const void *, const void *));

qsort(3)함수는 배열형태의 데이터를 정렬하는 함수입니다. 배열 형태라고 함은 데이터의 폭이 일정한 형태로 저장되어 있는 데이터를 정렬합니다. 배열이나 포인터로 malloc( )한 데이터가 연속적인 경우에 사용합니다. 실제 동작하는 방식은 아래의 예제 프로그램을 참조하시기 바랍니다.

 

 

파라미터

base
    - sorting을 할 원본 데이터. sorting의 결과 base 데이터 자체가 sorting된 형태로 변경됩니다.
    - base는 어떤 형태의 자료구조든지 상관없지만 각 데이터는 폭이 일정해야 합니다.
nmemb
    - sorting할 데이터 건 수
size
    - 1건의 데이터 크기
compar
    - 데이터의 sorting을 위한 로직이 구현된 함수 포인터
    - 이 함수 포인터의 return 값에 의해서 sorting 순서가 결정됩니다.
    - 두 데이터의 비교한 결과가 -이면 첫 파라미터가 앞쪽에 위치하게 됩니다.

 

 

RETURN

없음

 


예제). 정수형 배열의 오름 차순으로 정렬하기 (기본 데이터 타입)

#include <stdio.h>
#include <stdlib.h>

int intcmp(const void *v1, const void *v2)
{
    int *i1 = (int *)v1;
    int *i2 = (int *)v2;

    return *i1 - *i2;
}

int main()
{
    int array[10] = {0, -1, 5, -2, 100, };
    
    /* array의 크기는 10이지만 실제로 정렬할 부분은 5개이므로 5로 설정함 */
    qsort(array, 5, sizeof(int), intcmp);
    
    for(int i = 0; i < 5; i++)
        printf("%d ", array[i]);

    return 0;
}

 

예제). 정수형 배열의 오름 차순으로 정렬하기 (기본 데이터 타입)

#include <stdio.h>
#include <stdlib.h>

/* 내림차순으로 정렬은 뒤의 것을 기준으로 비교합니다. */
int intcmp_rev(const void *v1, const void *v2)
{
    int *i1 = (int *)v1;
    int *i2 = (int *)v2;

    return *i2 - *i1;
}

int main()
{
    int array[10] = {0, -1, 5, -2, 100, };
    
    /* array의 크기는 10이지만 실제로 정렬할 부분은 5개이므로 5로 설정함 */
    qsort(array, 5, sizeof(int), intcmp_rev);
    
    for(int i = 0; i < 5; i++)
        printf("%d ", array[i]);

    return 0;
}

 


 

예제). 구조체의 정렬

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct book_info
{
    int    book_no;
    char   author[30];
    char   title[200];
    double price;
};

/* 책의 관리번호 기준으로 오름차순으로 정렬한다면 */
int book_comp_book_no(const void *v1, const void *v2)
{
    struct book_info *book1 = (struct book_info *)v1;
    struct book_info *book2 = (struct book_info *)v2;

    return book1->book_no - book2->book_no;
}

/* 책의 저자 기준으로 오름차순으로 정렬한다면 */
int book_comp_author(const void *v1, const void *v2)
{
    struct book_info *book1 = (struct book_info *)v1;
    struct book_info *book2 = (struct book_info *)v2;

    return strcmp(book1->author, book2->author);
}

/* 책의 제목 기준으로 오름차순으로 정렬한다면 */
int book_comp_title(const void *v1, const void *v2)
{
    struct book_info *book1 = (struct book_info *)v1;
    struct book_info *book2 = (struct book_info *)v2;

    return strcmp(book1->title, book2->title);
}

/* 책의 가격 기준으로 오름차순으로 정렬한다면 */
int book_comp_price(const void *v1, const void *v2)
{
    struct book_info *book1 = (struct book_info *)v1;
    struct book_info *book2 = (struct book_info *)v2;

    if(book1->price < book2->price) {
        return -1;
    } else if(book1->price > book2->price) {
        return 1;
    } else {
        return 0;
    }
}

/* 
* 내림차순으로 정렬하려면 비교하는 부분을 boo1과 book2를 바꾸어주는 함수를 각각 만들어서 사용하면 됩니다.
*/

int main()
{
    int    total_size = 1024;
    int    cur_size   = 0; 
    struct book_info *books;

    books = (struct book_info*)malloc(sizeof(struct book_info) * total_size);
    
    for(cur_size = 0; cur_size < total_size; cur_size++) {
        // input book info...
        printf("Input Author: ");
        fgets(books[cur_size].author, 30, stdin);
        printf("Input Title: ");
        fgets(books[cur_size].title, 200, stdin);
        printf("Input Price: ");
        scanf("%lf", &books[cur_size].price);
    }
    
    /* 작가 기준으로 정렬한다면 */
    qsort(books, cur_size, sizeof(struct book_info), book_comp_author);
    
    for(int i = 0; i < cur_size; i++) {
        printf("No.%d ",  books[i].book_no);
        printf("%-30s ",  books[i].author);
        printf("%-200s ", books[i].title);
        printf("$%lf ",   books[i].price);
    }

    return 0;
}

일반적으로 구조체의 정렬은 구조체의 특정 멤버를 기준으로 정렬하는 경우가 일반적이므로 구조체의 특정 항목끼리 비교하는 함수를 각각 만들어야 합니다. 만약 복합 정렬(예, 작가 + 제목)을 한다면 아래와 같이 하면 됩니다.

 

예제) 복합 정렬(작가 + 제목)으로 정렬

/* 책의 저자 + 제목 기준으로 오름차순으로 정렬한다면 */
int book_comp_author_title(const void *v1, const void *v2)
{
    int    comp;
    
    comp = book_comp_author(v1, v2);
    /* 작가의 이름이 다른 경우 */
    if(comp != 0) {
        return comp;
    }
    
    /* 작가의 이름이 같은 경우 */
    return book_comp_title(v1, v2);
}

 

블로그 이미지

사용자 자연&사람

행복한 개발자 programmer since 1995.

댓글을 달아 주세요