การเรียงลำดับข้อมูล (Sorting) ถือเป็นหนึ่งในหัวใจของวิทยาการคอมพิวเตอร์ ซึ่ง Merge Sort หรือ การเรียงลำดับแบบผสาน เป็นหนึ่งในวิธีการที่ได้รับความนิยมสูง เพราะมันสามารถจัดการข้อมูลที่มีปริมาณมากได้อย่างมีประสิทธิภาพ วันนี้เราจะมาทำความรู้จักกับ Merge Sort ผ่านภาษาโปรแกรมมิ่งยอดนิยมอย่าง Java โดยจะหยิบยกทั้ง usecase ในโลกจริง, การวิเคราะห์ค่าความซับซ้อน (Complexity), ข้อดีข้อมีของวิธีการนี้ และไม่พลาดที่จะให้ตัวอย่าง code มาช่วยในการเข้าใจอีกด้วย
Merge Sort ถูกคิดค้นขึ้นในปี 1945 โดย John von Neumann และได้รับการยกให้เป็นหนึ่งในอัลกอริทึมการเรียงลำดับคลาสสิกที่มีประสิทธิภาพสูง เนื่องจากมีความซับซ้อนเชิงเวลา (Time Complexity) ในวิทยาการคอมพิวเตอร์ที่ค่อนข้างแน่นอนและสม่ำเสมอไม่ว่าข้อมูลจะเป็นอย่างไร
Merge Sort ทำงานบนหลักการของ 'การแบ่งและเ conquering' หรือ Divide and Conquer ซึ่งประกอบด้วย 2 ส่วนคือ:
1. Divide: แบ่งข้อมูลเป็นส่วนย่อยๆ จนถึงเมื่อไหร่ก็ตามที่ข้อมูลแต่ละส่วนมีเพียง 1 หรือ 0 องค์ประกอบ
2. Conquer: รวบรวมข้อมูลส่วนย่อยๆ กลับเข้าด้วยกัน (Merge) โดยเรียงลำดับองค์ประกอบที่ละคู่ให้กลายเป็นข้อมูลที่เรียงลำดับเรียบร้อยแล้ว
public class MergeSort {
public static void mergeSort(int[] array, int left, int right) {
if (left < right) {
// หาจุดกึ่งกลาง (Middle point)
int middle = left + (right - left) / 2;
// แบ่งข้อมูลและเรียก mergeSort ซ้ำทั้งสองด้าน
mergeSort(array, left, middle);
mergeSort(array, middle + 1, right);
// รวมข้อมูล
merge(array, left, middle, right);
}
}
private static void merge(int[] array, int left, int middle, int right) {
// หาขนาดของสองส่วนย่อยที่จะทำการรวม
int n1 = middle - left + 1;
int n2 = right - middle;
// สร้าง arrays ชั่วคราว
int L[] = new int[n1];
int R[] = new int[n2];
// คัดลอกข้อมูลไปยัง arrays ชั่วคราว
for (int i = 0; i < n1; ++i)
L[i] = array[left + i];
for (int j = 0; j < n2; ++j)
R[j] = array[middle + 1 + j];
// ผสานรวม arrays ชั่วคราว
// กำหนด index เริ่มต้นของสอง array ชั่วคราว
int i = 0, j = 0;
// กำหนด index เริ่มต้นของ array ผสาน
int k = left;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
array[k] = L[i];
i++;
} else {
array[k] = R[j];
j++;
}
k++;
}
// คัดลอก data ที่เหลือจาก L[] ถ้ามี
while (i < n1) {
array[k] = L[i];
i++;
k++;
}
// คัดลอก data ที่เหลือจาก R[] ถ้ามี
while (j < n2) {
array[k] = R[j];
j++;
k++;
}
}
// ฟังก์ชันสำหรับ print ผลลัพธ์
static void printArray(int arr[]) {
int n = arr.length;
for (int i = 0; i < n; ++i)
System.out.print(arr[i] + " ");
System.out.println();
}
// ตัวอย่างการใช้งาน
public static void main(String args[]) {
int arr[] = { 12, 11, 13, 5, 6, 7 };
System.out.println("Given Array");
printArray(arr);
MergeSort.mergeSort(arr, 0, arr.length - 1);
System.out.println("\nSorted array");
printArray(arr);
}
}
Merge Sort มีประโยชน์มากในสถานการณ์ที่มีข้อมูลใหญ่โต เช่น การจัดเรียงข้อมูลในฐานข้อมูลขนาดใหญ่ หรือการผสานข้อมูลจากหลายแหล่งมาเรียงลำดับเพื่อการวิเคราะห์ เช่น ในระบบบันทึกข้อมูลทางการแพทย์ การเรียงลำดับการทำงานในระบบการผลิต หรือแม้กระทั่งในเทคโนโลยี Big Data ที่ต้องขยายและเรียงลำดับข้อมูลอย่างต่อเนื่อง อีกทั้งยังใช้ในการโปรแกรมที่นำเสนอผลลัพธ์ให้กับผู้ใช้งานได้เร็วขึ้น และสามารถรับมือกับการเปลี่ยนแปลงของข้อมูลได้โดยไม่ต้องเริ่มต้นเรียงลำดับใหม่ทั้งหมด
Complexity ของ Merge Sort ในทุกกรณี (Worst, Average, และ Best case) คือ O(n log n) ด้วยเหตุนี้มันจึงมีความได้เปรียบเมื่อเทียบกับอัลกอริทึมการเรียงลำดับที่มีความซับซ้อนเชิงเวลามากกว่าเมื่อข้อมูลมีขนาดใหญ่ อย่างไรก็ตาม Merge Sort ยังมีข้อเสียในทาง Space Complexity เพราะมันต้องการพื้นที่เพิ่มเติมสำหรับ arrays ชั่วคราวในการผสานข้อมูลคืน
ข้อดี
:
- มีประสิทธิภาพสม่ำเสมอในทุกกรณี กับความซับซ้อนเชิงเวลา O(n log n)
- เหมาะสมกับการเรียงลำดับข้อมูลจำนวนมาก
- ไม่ต้องพึ่งพาการเรียงลำดับของข้อมูลเดิม (ไม่ใช่ in-place sorting), ทำให้เหมาะกับ Linked List
ข้อเสีย
:
- ต้องการพื้นที่หน่วยความจำเพิ่มเติมในการเก็บ arrays ชั่วคราว
- อาจไม่เหมาะสมกับการเรียงข้อมูลที่มีขนาดเล็ก (เพราะอาจจะมี overhead จากการทำ recursive calls มากเกินไป)
ในบทสรุป Merge Sort เป็นวิธีการเรียงลำดับที่มีความสมบูรณ์แบบกับข้อมูลขนาดใหญ่หรือต้องการความแม่นยำในการเรียงลำดับ หากคุณชื่นชอบการเรียนรู้เกี่ยวกับอัลกอริทึมและต้องการพัฒนาทักษะการเขียนโปรแกรมของคุณในระดับที่ลึกล้ำยิ่งขึ้น สถาบัน EPT (Expert-Programming-Tutor) พร้อมเป็นพาหนะนำพาคุณไปยังโลกของการเข้าใจซอฟต์แวร์และอัลกอริทึมในระดับมืออาชีพ ณ ที่นี่ เรามุ่งเน้นในการสร้างและแบ่งปันความรู้ทางด้านการโปรแกรมมิ่งผ่านการสอนที่ใส่ใจและมีคุณภาพ เพื่อการเรียนรู้ที่ไม่มีที่สิ้นสุดในการเป็นนักพัฒนาซอฟต์แวร์ที่ยอดเยี่ยม!
หมายเหตุ: ข้อมูลในบทความนี้อาจจะผิด โปรดตรวจสอบความถูกต้องของบทความอีกครั้งหนึ่ง บทความนี้ไม่สามารถนำไปใช้อ้างอิงใด ๆ ได้ ทาง EPT ไม่ขอยืนยันความถูกต้อง และไม่ขอรับผิดชอบต่อความเสียหายใดที่เกิดจากบทความชุดนี้ทั้งทางทรัพย์สิน ร่างกาย หรือจิตใจของผู้อ่านและผู้เกี่ยวข้อง
Tag ที่น่าสนใจ: merge_sort java algorithm sorting divide_and_conquer complexity_analysis programming data_structures recursive arrays linked_list space_complexity time_complexity big_data
หากมีข้อผิดพลาด/ต้องการพูดคุยเพิ่มเติมเกี่ยวกับบทความนี้ กรุณาแจ้งที่ http://m.me/Expert.Programming.Tutor
085-350-7540 (DTAC)
084-88-00-255 (AIS)
026-111-618
หรือทาง EMAIL: NTPRINTF@GMAIL.COM