0Pricing
C Academy · บทเรียน

qsort กับตัวเปรียบเทียบ

การเรียกกลับจากไลบรารีมาตรฐาน

qsort กับตัวเปรียบเทียบ เป็นบทเรียน C Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน

qsort มาตรฐาน

ไลบรารีมาตรฐานมี qsort ใน <stdlib.h> ซึ่งเป็นการเรียงลำดับทั่วไปที่ใช้ได้กับอาร์เรย์ทุกชนิดผ่านฟังก์ชันเรียกกลับสำหรับเปรียบเทียบ

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

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

int main(void) {
    int a[] = {3, 1, 2};
    qsort(a, 3, sizeof(int), cmp_int);
    printf("%d %d %d\n", a[0], a[1], a[2]);
    return 0;
}

รูปแบบฟังก์ชันของ qsort

qsort(base, count, size, compare) รับจุดเริ่มต้นของอาร์เรย์ จำนวนสมาชิก ขนาดสมาชิก และฟังก์ชันเปรียบเทียบ

ฟังก์ชันนี้เป็นแบบทั่วไป เพราะทำงานกับไบต์ดิบร่วมกับฟังก์ชันเปรียบเทียบของคุณ

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

int cmp(const void *a, const void *b) {
    return *(const int*)a - *(const int*)b;
}

int main(void) {
    int a[] = {9, 4, 7, 1};
    qsort(a, 4, sizeof(int), cmp);
    for (int i = 0; i < 4; i++) printf("%d ", a[i]);
    printf("\n");
    return 0;
}

ข้อตกลงของฟังก์ชันเปรียบเทียบ

ฟังก์ชันเปรียบเทียบคืนค่าลบหากสมาชิกตัวแรกควรอยู่ก่อนตัวที่สอง คืนค่าศูนย์หากเท่ากัน และคืนค่าบวกหากควรอยู่หลัง

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

int cmp(const void *a, const void *b) {
    int x = *(const int*)a, y = *(const int*)b;
    if (x < y) return -1;
    if (x > y) return 1;
    return 0;
}

int main(void) {
    int a[] = {5, 2, 8, 2};
    qsort(a, 4, sizeof(int), cmp);
    for (int i = 0; i < 4; i++) printf("%d ", a[i]);
    printf("\n");
    return 0;
}

การแปลงพอยน์เตอร์ void

ฟังก์ชันเปรียบเทียบรับ const void * สำหรับสมาชิกแต่ละตัว ให้แปลงเป็นชนิดที่ถูกต้อง แล้วถอดการอ้างอิงเพื่ออ่านค่า

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

int cmp(const void *a, const void *b) {
    double x = *(const double*)a;
    double y = *(const double*)b;
    return (x > y) - (x < y);
}

int main(void) {
    double d[] = {2.5, 1.1, 3.3};
    qsort(d, 3, sizeof(double), cmp);
    printf("%.1f %.1f %.1f\n", d[0], d[1], d[2]);
    return 0;
}

ลำดับจากมากไปน้อย

กลับผลการเปรียบเทียบเพื่อเรียงจากค่ามากไปหาค่าน้อย

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

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

int main(void) {
    int a[] = {1, 5, 3, 2};
    qsort(a, 4, sizeof(int), desc);
    for (int i = 0; i < 4; i++) printf("%d ", a[i]);
    printf("\n");
    return 0;
}

หลีกเลี่ยงค่าล้นจากการลบ

การคืนค่า x - y อาจทำให้เกิดค่าล้นเมื่อจำนวนเต็มมีขนาดใหญ่ สำนวนที่ปลอดภัยอย่าง (x > y) - (x < y) จะหลีกเลี่ยงปัญหานี้

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

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

int main(void) {
    int a[] = {100, -100, 0};
    qsort(a, 3, sizeof(int), safe_cmp);
    for (int i = 0; i < 3; i++) printf("%d ", a[i]);
    printf("\n");
    return 0;
}

การเรียงลำดับสตริง

สำหรับอาร์เรย์ของ char * สมาชิกแต่ละตัวเป็นพอยน์เตอร์ ดังนั้นให้แปลงเป็น const char * const * แล้วเปรียบเทียบด้วย strcmp

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

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

int main(void) {
    const char *w[] = {"pear", "apple", "fig"};
    qsort(w, 3, sizeof(char*), cmp_str);
    for (int i = 0; i < 3; i++) printf("%s ", w[i]);
    printf("\n");
    return 0;
}

การเรียงลำดับโครงสร้าง

qsort จัดการอาร์เรย์ของโครงสร้างได้เช่นกัน ให้เปรียบเทียบฟิลด์ที่เลือกไว้ภายในฟังก์ชันเปรียบเทียบ

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

typedef struct { char name; int age; } Person;

int by_age(const void *a, const void *b) {
    int x = ((const Person*)a)->age;
    int y = ((const Person*)b)->age;
    return (x > y) - (x < y);
}

int main(void) {
    Person p[] = {{'C',30},{'A',20},{'B',25}};
    qsort(p, 3, sizeof(Person), by_age);
    for (int i = 0; i < 3; i++) printf("%c:%d ", p[i].name, p[i].age);
    printf("\n");
    return 0;
}

bsearch ใช้แนวคิดเดียวกัน

bsearch ค้นหาแบบทวิภาคในอาร์เรย์ที่เรียงแล้ว โดยใช้ฟังก์ชันเปรียบเทียบที่มีข้อตกลงเดียวกับ qsort

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

int cmp(const void *a, const void *b) {
    return (*(const int*)a) - (*(const int*)b);
}

int main(void) {
    int a[] = {1, 3, 5, 7, 9};
    int key = 7;
    int *found = bsearch(&key, a, 5, sizeof(int), cmp);
    printf("found: %d\n", found ? *found : -1);
    return 0;
}

คีย์สำหรับเรียงลำดับหลายระดับ

ฟังก์ชันเปรียบเทียบสามารถเปรียบเทียบฟิลด์หลักก่อน แล้วเปรียบเทียบฟิลด์รองเมื่อค่าหลักเท่ากัน

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

typedef struct { int grade; int id; } Rec;

int cmp(const void *a, const void *b) {
    const Rec *x = a, *y = b;
    if (x->grade != y->grade) return x->grade - y->grade;
    return x->id - y->id;
}

int main(void) {
    Rec r[] = {{90,2},{90,1},{80,3}};
    qsort(r, 3, sizeof(Rec), cmp);
    for (int i = 0; i < 3; i++) printf("%d/%d ", r[i].grade, r[i].id);
    printf("\n");
    return 0;
}

เหตุใดการเรียงลำดับทั่วไปจึงสำคัญ

เนื่องจาก qsort แยกอัลกอริทึมออกจากการเปรียบเทียบ ฟังก์ชันเดียวที่ผ่านการทดสอบอย่างดีจึงสามารถเรียงลำดับข้อมูลทุกชนิดที่เปรียบเทียบได้

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

int cmp(const void *a, const void *b) {
    char x = *(const char*)a, y = *(const char*)b;
    return (x > y) - (x < y);
}

int main(void) {
    char s[] = "dcba";
    qsort(s, 4, sizeof(char), cmp);
    printf("%s\n", s);
    return 0;
}

ตรวจสอบความเข้าใจ

ทดสอบความเข้าใจเรื่องฟังก์ชันเปรียบเทียบของ qsort

สรุป

คุณได้เรียนรู้การใช้ qsort ร่วมกับฟังก์ชันเปรียบเทียบ:

  • qsort(base, count, size, compare) เรียงลำดับอาร์เรย์ทุกชนิดแบบทั่วไป
  • ฟังก์ชันเปรียบเทียบรับ const void * สองค่า และคืนค่าลบ ศูนย์ หรือบวก
  • ใช้ (x > y) - (x < y) เพื่อหลีกเลี่ยงค่าล้น
  • ข้อตกลงเดียวกันนี้ใช้กับ bsearch การเรียงโครงสร้าง และการเรียงด้วยหลายคีย์

คำถามที่พบบ่อย

บทเรียน “qsort กับตัวเปรียบเทียบ” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “qsort กับตัวเปรียบเทียบ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “qsort กับตัวเปรียบเทียบ”

การเรียกกลับจากไลบรารีมาตรฐาน คุณปฏิบัติ C Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “qsort กับตัวเปรียบเทียบ” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C Academy นี้ได้ไหม

ได้ บทเรียน C Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การประกาศพอยน์เตอร์ฟังก์ชัน
  2. การส่งฟังก์ชัน
  3. qsort กับตัวเปรียบเทียบ
  4. ตารางพอยน์เตอร์ฟังก์ชัน
← กลับไปที่ C Academy