การเรียงลำดับภายนอก

การเรียงลำดับภายนอก (external sorting) หรือขั้นตอนวิธีผสานหลายเส้นทาง (k-way Merge Algorithm) เป็นการแก้ปัญหาโดยใช้หลักการแก้ที่เรียกว่า การแบ่งแยกและเอาชนะ (Divide & Conquer) โดยขั้นตอนนี้ใช้เพื่อเรียงลำดับข้อมูลที่รับมาจากน้อยไปมาก โดยสมมติว่าข้อมูลที่รับเข้ามาเป็นรายการที่มีสมาชิก n ตัว หากเราเรียงลำดับแบบปกติคือไล่จับคู่ทีละคู่ เพื่อเปรียบเทียบว่าตัวใดน้อยกว่า แล้วเรียงลำดับจนครบทุกคู่ จะมีประสิทธิภาพเชิงเวลาคือ O(n2) ซึ่งถือว่าค่อนข้างมากเลยทีเดียว เราสามารถลดเวลาที่ใช้ได้โดยเราจะแบ่งข้อมูลออกเป็น k รายการ โดยแต่ละรายการจะมีจำนวนข้อมูลเท่า ๆ กัน คือ ⌊n / k⌋ ซึ่งหากแบ่งเท่า ๆ กันไม่ได้ อาจจะมีบางรายการมีจำนวนข้อมูลเป็น ⌊n / k⌋ + 1 จากนั้นทำการเรียงลำดับข้อมูลทั้ง k รายการ แล้วนำกลับมาผสานกันกลายเป็นรายการเดียวที่มีการเรียงลำดับเรียบร้อย
== การอธิบายขั้นตอน ==
หลังจากทำการเรียงลำดับข้อมูลทั้ง k รายการแล้ว เรามีอัลกอริธึมสำหรับผสานข้อมูลทั้ง k รายการเป็นรายการเดียวอยู่ 3 แบบ
ผสานโดยการค้นหาแบบเชิงเส้น นำค่าที่น้อยที่สุดของแต่ละรายการมาหาค่าน้อยทีสุด เมื่อได้ค่านั้นแล้วให้ทำการลบค่านั้นของจากรายการที่มันอยู่แล้วไปใส่ไว้รายการคำตอบ จากนั้นทำการจัดลำดับรายการที่เอาค่านั้นออกมาใหม่ (ในกรณีที่รายการนั้นไม่มีสมาชิกเหลือแล้วให้ใส่เป็นค่า null โดยค่า null จะไม่ถูกนำมาเปรียบเทียบเพื่อหาค่าน้อยที่สุด) แล้วกลับไปเริ่มพิจารณาหาค่าที่น้อยที่สุดของแต่ละรายการอีกรอบ ทำแบบนี้ไปเรื่อย ๆ จนกว่าข้อมูลของแต่ละรายการจะหมด จะได้รายการคำตอบที่ข้อมูลภายในนั้นเป็นข้อมูลที่มีการจัดเรียงไว้เรียบร้อยแล้ว
ผสานโดยการใช้ฮีป นำค่าน้อยที่สุดของทั้ง k รายการมาใส่ลงในฮีปน้อยสุด (จากคุณสมบัติของฮีปน้อยสุดจะได้ค่าที่น้อยที่สุดเป็นรากเสมอ) จากนั้นนำค่าของรากนั้นไปใส่ในรายการคำตอบ แล้วแทนที่ค่าของรากนั้นด้วยค่าที่น้อยเป็นอันดับถัดมาจากรายการที่รากนั้นอยู่ ทำการปรับต้นไม้ จากนั้นกลับไปดึงค่าของรากไปใส่ในรายการคำตอบอีกรอบ ทำแบบนี้ไปเรื่อยจนกว่าฮีปจะมีสมาชิกเป็น 0
ผสานโดยใช้หลักการแบ่งแยกและเอาชนะ ใช้หลักการเวียนเกิด โดยแบ่งรายการออกเป็น 2 ส่วนไปเรื่อย ๆ จนกว่าจะเป็นกรณีเล็กที่สุดเท่าที่กำหนด จากนั้นค่อยผสานผลลัพธ์ทีละ 2 ส่วนเข้าด้วยกันจนกลับมาเป็นก้อนใหญ่เท่าตอนแรก
== รหัสเทียมและประสิทธิภาพเชิงเวลา ==
=== ผสานโดยการค้นหาแบบเชิงเส้น ===
ต้องใช้เวลาในการวนจนครบข้อมูลทุกตัวจึงเสียเวลา n รอบ โดยแต่ละรอบต้องวนเปรียบเทียบค่าน้อยที่สุดของแต่ละรายการเพื่อหาค่าน้อยที่สุดมาใส่รายการคำตอบ เนื่องจากมีทั้งหมด k รายการ เวลาที่มากที่สุดในการวนตรวจสอบจึงเป็น k รอบ
→ ประสิทธิภาพเชิงเวลาของวิธีนี้จึงเป็น O(nk)
=== ผสานโดยการใช้ฮีป ===
ข้อมูลทุกตัวต้องถูกนำมาใส่ในฮีปจึงเสียเวลาทั้งหมด n รอบ โดยแต่ละรอบเมื่อมีการดึงค่ารากออกไปใส่ในรายการคำตอบ แล้วแทนที่ค่าของรากนั้นด้วยค่าที่น้อยกว่าเป็นอันดับรองลงมาจากรายการเดียวกับที่ค่ารากนั้นอยู่ ทำให้ต้องเสียเวลาในการปรับฮีปเป็นเวลาอย่างมาก log k
→ ประสิทธิภาพเชิงเวลาของวิธีนี้จึงเป็น O(n log k)
=== ผสานโดยใช้หลักการแบ่งแยกและเอาชนะ ===
จากรหัสเทียมจะเห็นได้ว่าข้อมูลจะถูกแบ่งเป็นครึ่ง ๆ ไปเรื่อย ๆ จนกว่าข้อมูลที่พิจารณาจะเป็นกรณีเล็กที่สุดเท่าที่กำหนดนั่นก็คือรายการเดียว แล้วค่อยผสานกลับขึ้นมาจนกลายเป็นรายการที่มีขนาดเท่าจำนวนข้อมูล ประสิทธิภาพเชิงเวลาสามารถหาได้จากการใช้ต้นไม้แสดงภาระจริง
→ ประสิทธิภาพเชิงเวลาของวิธีนี้จึงเป็น O(n log k)
== พิสูจน์ความถูกต้อง ==
หากค่าที่น้อยที่สุดของข้อมูลแต่ละรายการเป็น min1 , min2 , min3 , … , mink ค่าที่น้อยที่สุดของค่าเหล่านี้ย่อมเป็นค่าที่น้อยที่สุดของข้อมูลด้วย
จากหลักการนี้ ทั้งวิธี ผสานโดยการค้นหาแบบเชิงเส้น และ ผสานโดยการใช้ฮีป ใช้หลักการแบบเดียวกัน คือหาค่าที่น้อยที่สุดจากค่าที่น้อยสุดของทั้ง k รายการมาเติมลงในรายการคำตอบเรื่อย ๆ ดังนั้นรายการคำตอบจะถูกเติมเรื่อย ๆ จากน้อยไปมากจนครบข้อมูลทุกตัว
ส่วนวิธี ผสานโดยใช้หลักการแบ่งแยกและเอาชนะ ใช้หลักการผสานและเรียงลำดับไปด้วย จากข้อมูลย่อย ๆ ไปจนเท่าขนาดข้อมูลจริง ทำให้ได้ผลเหมือนการเรียงลำดับทีเดียวทั้งหมดเลย แต่จะใช้เวลาน้อยกว่า
== ตัวอย่างการประยุกต์ใช้งาน ==
จากตัวอย่างจะเห็นได้ว่าขั้นตอนวิธีผสานหลายเส้นทางสามารถใช้ในการผสานข้อมูลให้เรียงลำดับข้อมูลได้ ซึ่งเราสามารถกำหนดได้ว่าจะเรียงจากน้อยไปมาก หรือมากไปน้อย โดยเราสามารถนำสิ่งนี้ไปประยุกต์ใช้ในชีวิตประจำวันได้โดยที่หลักการยังคงเป็นแบบเดิม
เช่น ในการเรียงลำดับของข้อมูลของสินค้าต่าง ๆ ในคลังเก็บสินค้า เราสามารถเรียงได้หลายแบบ
เรียงตามราคาจากน้อยไปมาก
เรียงตามค่าดัชนีที่กำหนดให้สินค้าแต่ละตัวเพื่อใช้ในการเรียงลำดับโดยเฉพาะ
เรียงตามตัวอักษรที่นำหน้าชื่อสินค้าตามลำดับพจนานุกรม
จะเห็นได้ว่าวิธีการผสานหลายเส้นทางจะมีส่วนช่วยลดเวลาในส่วนของการเรียงลำดับได้มากทีเดียว
== อ้างอิง ==
.
.
ขั้นตอนวิธีการเรียงลำดับ