Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Hàm so sánh (Comparator) của qsort() trong C

Hàm qsort() (Quick Sort) trong thư viện chuẩn C (<stdlib.h>) sắp xếp mảng bất kỳ kiểu dữ liệu nào nhờ con trỏ void* và hàm so sánh do người dùng cung cấp.

Chữ ký hàm so sánh

int comparator(const void *p1, const void *p2);

Quy tắc trả về

Trả vềÝ nghĩaThứ tự
< 0Phần tử *p1 nhỏ hơn *p2p1 đứng trước p2
== 0Hai phần tử bằng nhauGiữ nguyên thứ tự (không ổn định)
> 0Phần tử *p1 lớn hơn *p2p1 đứng sau p2

Triển khai cho các kiểu cơ bản

Số nguyên (int)

int cmp_int(const void *a, const void *b) {
    int arg1 = *(const int*)a;
    int arg2 = *(const int*)b;
    if (arg1 < arg2) return -1;
    if (arg1 > arg2) return 1;
    return 0;
    // Hoặc gọn: return (arg1 > arg2) - (arg1 < arg2); // Tránh tràn số
}

Số thực (double)

int cmp_double(const void *a, const void *b) {
    double arg1 = *(const double*)a;
    double arg2 = *(const double*)b;
    return (arg1 > arg2) - (arg1 < arg2);
}

Chuỗi (char*)

int cmp_str(const void *a, const void *b) {
    const char *arg1 = *(const char**)a;
    const char *arg2 = *(const char**)b;
    return strcmp(arg1, arg2);
}

Ví dụ: Sắp xếp struct Sách theo giá

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

typedef struct {
    char title[50];
    int pages;
    float price;
} Book;

int compare_book(const void *a, const void *b) {
    Book *b1 = (Book*)a;
    Book *b2 = (Book*)b;
    // Sắp xếp tăng dần theo price
    if (b1->price < b2->price) return -1;
    if (b1->price > b2->price) return 1;
    return 0;
}

int main() {
    Book books[5] = {
        {"C Programming", 260, 450.0},
        {"DBMS Guide", 850, 775.0},
        {"Learn C++", 350, 520.0},
        {"Data Structures", 380, 430.0},
        {"Learn Python", 500, 300.0}
    };
    
    int n = 5;
    qsort(books, n, sizeof(Book), compare_book);
    
    printf("%-20s %5s %10s\n", "Tieu de", "Trang", "Gia");
    for (int i = 0; i < n; i++) {
        printf("%-20s %5d %10.2f\n", books[i].title, books[i].pages, books[i].price);
    }
    return 0;
}

Kết quả

Tieu de                Trang       Gia
Learn Python             500     300.00
Data Structures          380     430.00
C Programming            260     450.00
Learn C++                350     520.00
DBMS Guide               850     775.00

Lưu ý quan trọng

  • Luôn ép kiểu const void* về kiểu thực tế bên trong comparator.
  • Tránh trừ trực tiếp return *a - *b cho số nguyên — có thể tràn số (overflow) khi giá trị lớn. Dùng so sánh điều kiện hoặc (a>b)-(a.
  • qsort không ổn định (unstable): các phần tử bằng nhau có thể đổi chỗ thứ tự.
  • C++ nên dùng std::sort với lambda/comparator functor — an toàn kiểu, nhanh hơn, ổn định (stable_sort).

Nắm vững comparator là chìa khóa để dùng qsort linh hoạt cho mọi cấu trúc dữ liệu.