1. ภาพรวมของฟังก์ชัน qsort
ฟังก์ชัน qsort
ที่มีให้ในไลบรารีมาตรฐานของภาษา C เป็นเครื่องมือที่ทรงพลังสำหรับการเรียงลำดับองค์ประกอบในอาเรย์ qsort
ใช้อัลกอริทึม Quick Sort ซึ่งสามารถจัดเรียงข้อมูลได้อย่างรวดเร็วและมีประสิทธิภาพสูง ส่วนนี้จะอธิบายกลไกพื้นฐานของ qsort
และเหตุผลที่ฟังก์ชันนี้มีความสำคัญ
qsort คืออะไร?
qsort
เป็นฟังก์ชันทั่วไปที่ใช้เรียงลำดับข้อมูลในอาเรย์หรือรายการตามฟังก์ชันเปรียบเทียบที่ผู้ใช้กำหนดเอง เป็นฟังก์ชันมาตรฐานของภาษา C และถูกใช้อย่างกว้างขวางในงานพัฒนาซอฟต์แวร์ต่าง ๆ ตัวอย่างเช่น สามารถเรียงลำดับอาเรย์ของจำนวนเต็ม อาเรย์ของสตริง หรือข้อมูลที่เป็นโครงสร้าง struct ได้อย่างมีประสิทธิภาพ
#include <stdio.h>
#include <stdlib.h>
int compare(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
int main() {
int values[] = {40, 10, 100, 90, 20, 25};
size_t values_len = sizeof(values)/sizeof(values[0]);
qsort(values, values_len, sizeof(int), compare);
for(int i = 0; i < values_len; i++) {
printf("%d ", values[i]);
}
return 0;
}
โค้ดข้างต้นเป็นตัวอย่างพื้นฐานของการใช้ qsort
เพื่อเรียงลำดับอาเรย์ของจำนวนเต็ม โดยใช้ฟังก์ชันเปรียบเทียบเพื่อกำหนดลำดับข้อมูล
2. อาร์กิวเมนต์และวิธีการใช้ qsort
รูปแบบโปรโตไทป์ของ qsort
มีดังนี้:
void qsort(void *base, size_t num, size_t size, int (*compar)(const void *, const void *));
รายละเอียดของอาร์กิวเมนต์
- base: พอยน์เตอร์ไปยังอาเรย์ที่จะเรียงลำดับ
- num: จำนวนองค์ประกอบในอาเรย์
- size: ขนาดของแต่ละองค์ประกอบ (หน่วยเป็นไบต์)
- compar: พอยน์เตอร์ไปยังฟังก์ชันเปรียบเทียบ
ฟังก์ชันนี้จะเรียงลำดับองค์ประกอบตามฟังก์ชันเปรียบเทียบ compar
ซึ่งรับอาร์กิวเมนต์สองตัวและคืนค่าที่บ่งบอกว่าองค์ประกอบไหนมีค่ามากกว่าหรือน้อยกว่า ความยืดหยุ่นนี้ช่วยให้สามารถเรียงลำดับข้อมูลหลายประเภทได้
การสร้างฟังก์ชันเปรียบเทียบ
ฟังก์ชันเปรียบเทียบเป็นหัวใจหลักของการทำงานของ qsort สามารถนิยามฟังก์ชันเปรียบเทียบระหว่างองค์ประกอบได้ดังนี้:
int compare(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
ฟังก์ชันนี้จะเปรียบเทียบค่าระหว่าง a
กับ b
ถ้า a
น้อยกว่าจะคืนค่าเป็นลบ เท่ากันคืนค่า 0 มากกว่าจะคืนค่าเป็นบวก ซึ่งจะทำให้ qsort
เรียงลำดับอาเรย์ในรูปแบบ ascending
3. การทำงานภายในของ qsort: อัลกอริทึม Quick Sort
qsort
ใช้อัลกอริทึม Quick Sort ภายใน ซึ่งเป็นอัลกอริทึมแบบแบ่งแยกและพิชิต โดยมีขั้นตอนดังนี้:
- การเลือก Pivot: เลือกองค์ประกอบตรงกลางหรือท้ายอาเรย์เป็น pivot (จุดอ้างอิง)
- การแบ่ง: ย้ายองค์ประกอบที่มีค่าน้อยกว่า pivot ไปด้านซ้าย และค่ามากกว่าไปด้านขวา
- การเรียงแบบวนซ้ำ (recursion): ทำซ้ำกระบวนการกับอาเรย์ย่อยที่ถูกแบ่ง
การสลับและแบ่งซ้ำนี้ทำให้สามารถเรียงลำดับอาเรย์ได้อย่างมีประสิทธิภาพ Quick Sort มีค่าเฉลี่ย O(n log n) เมื่อเทียบกับอัลกอริทึมอื่น ๆ จึงทำงานได้รวดเร็วมาก แต่ในกรณีที่แย่ที่สุด (เช่น อาเรย์เรียงอยู่แล้ว) จะใช้เวลา O(n^2)

4. วิธีสร้างฟังก์ชันเปรียบเทียบ
ข้อดีของ qsort
คือสามารถสร้างฟังก์ชันเปรียบเทียบแบบกำหนดเองสำหรับชนิดข้อมูลต่าง ๆ ได้ ตัวอย่างเช่น:
ฟังก์ชันเปรียบเทียบจำนวนเต็ม
int compare_int(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
ฟังก์ชันเปรียบเทียบสตริง
int compare_str(const void *a, const void *b) {
return strcmp(*(const char**)a, *(const char**)b);
}
ฟังก์ชันเปรียบเทียบโครงสร้าง struct
struct Person {
int id;
const char* name;
};
int compare_person(const void *a, const void *b) {
return ((struct Person*)a)->id - ((struct Person*)b)->id;
}
ด้วยวิธีนี้ qsort
จึงสามารถเรียงลำดับข้อมูลในอาเรย์ได้หลากหลายรูปแบบด้วยฟังก์ชันเปรียบเทียบที่เหมาะสม
5. การเรียงลำดับอาเรย์ของ struct ด้วย qsort
เมื่อต้องเรียงลำดับอาเรย์ที่ประกอบด้วย struct qsort
ก็มีประสิทธิภาพสูง เช่น อาเรย์ของ struct Person
ที่เรียงตามฟิลด์ id
สามารถทำได้ดังนี้:
struct Person people[] = {
{1, "Alice"},
{3, "Charlie"},
{2, "Bob"}
};
qsort(people, 3, sizeof(struct Person), compare_person);
โดยใช้ฟังก์ชัน compare_person
เพื่อเรียงลำดับตาม id
จะได้ผลลัพธ์เป็น Alice
, Bob
, Charlie
ตามลำดับ
6. การปรับแต่งประสิทธิภาพและเปรียบเทียบกับอัลกอริทึมอื่น
ประสิทธิภาพของ Quick Sort
Quick Sort มีประสิทธิภาพสูงสำหรับข้อมูลที่มีลักษณะสุ่ม โดยมีค่าเฉลี่ย O(n log n) อย่างไรก็ตาม ถ้าข้อมูลถูกเรียงอยู่แล้ว อาจเจอกรณีแย่สุดที่เป็น O(n^2) ดังนั้นสำหรับชุดข้อมูลบางกรณี อาจต้องเลือกใช้อัลกอริทึมอื่น
เปรียบเทียบกับ Heap Sort
Heap Sort มีค่าเวลา O(n log n) แม้ในกรณีแย่ที่สุด ให้ประสิทธิภาพที่เสถียรกว่า Quick Sort แต่โดยทั่วไป Quick Sort มักจะเร็วกว่าสำหรับข้อมูลแบบสุ่ม
เปรียบเทียบกับ Merge Sort
Merge Sort ก็มี O(n log n) และเป็นอัลกอริทึมที่มีความเสถียร (องค์ประกอบที่เท่ากันจะรักษาลำดับเดิม) ถ้าต้องการความเสถียรควรเลือก Merge Sort ส่วน Quick Sort ไม่คงลำดับของข้อมูลที่มีค่าเท่ากัน แต่ในการใช้งานปกติ มักไม่มีผลมากนัก
7. สรุป
qsort
เป็นฟังก์ชันเรียงลำดับที่มีประสิทธิภาพในภาษา C ด้วยความยืดหยุ่นและความเร็ว จึงถูกนำไปใช้ในโปรแกรมจำนวนมาก สามารถจัดการข้อมูลที่หลากหลายได้ผ่านฟังก์ชันเปรียบเทียบที่ผู้ใช้กำหนดเอง
หากเข้าใจหลักการของ Quick Sort จะสามารถใช้ qsort
ได้อย่างมีประสิทธิภาพยิ่งขึ้น ในบางกรณีควรพิจารณาเปรียบเทียบกับ Heap Sort หรือ Merge Sort เพื่อเลือกวิธีที่เหมาะสมกับข้อมูลและความต้องการของโปรเจกต์
ขอให้ลองนำ qsort
ไปใช้กับโปรเจกต์จริงของคุณ เพื่อพัฒนาโปรแกรมที่มีประสิทธิภาพมากขึ้น