Collision Handling (Chaining / Open Addressing) แบบละเอียด
บทนี้จะอธิบายแบบเป็นระบบว่า collision คืออะไร ทำไมเกิดขึ้นได้ และควรจัดการอย่างไรด้วย Chaining หรือ Open Addressing พร้อมตัวอย่างทีละขั้นสำหรับผู้เริ่มต้นถึงระดับกลาง
1. Collision คืออะไร
การชนกันของข้อมูล (collision) คือเหตุการณ์ที่ key คนละค่า ถูกแฮชไปที่ index เดียวกันในตารางแฮช (Hash Table)
แม้ key ต่างกัน แต่ตำแหน่งปลายทางอาจเหมือนกันได้ เพราะจำนวนช่องในตารางมีจำกัด
2. ทำไม collision เกิดขึ้นได้ แม้มี hash function
hash function แปลง key เป็นตัวเลข แล้วแปลงต่อเป็น index ด้วย mod ถ้าจำนวน key มากกว่าจำนวน slot หรือการกระจายไม่ดี โอกาสชนจะสูงขึ้น
3. ยกตัวอย่าง key ที่ให้ index ซ้ำกัน
สมมติ tableSize = 8 และใช้ hash แบบผลรวม charCode + mod key "ab" กับ "ba" อาจได้ index เดียวกัน
key ต่างกัน แต่ index ซ้ำกัน
4. ทำไม collision ต้องถูกจัดการ
ถ้าไม่จัดการ collision เราจะไม่สามารถเก็บหรือค้นข้อมูลได้ถูกต้อง เพราะหลาย key แย่งช่องเดียวกัน
การจัดการที่ดีช่วยรักษาความเร็วของ insert/search/delete ให้อยู่ในระดับที่ใช้งานได้จริง
5. วิธีที่ 1: Chaining คืออะไร
Chaining คือการให้แต่ละ bucket เก็บได้หลายรายการ โดยเก็บเป็นลิสต์ (list) หรือโครงสร้างที่คล้ายกัน
6. Chaining ทำงานอย่างไร
- คำนวณ index ของ key
- ไปที่ bucket index นั้น
- ถ้า key ซ้ำให้ update ค่า
- ถ้า key ใหม่ให้เพิ่ม node ต่อท้าย list
7. ตัวอย่าง bucket ที่เก็บหลายรายการเป็น list
หนึ่ง bucket เก็บหลายคู่ key-value
8. ข้อดีข้อเสียของ Chaining
ข้อดี
- จัดการ collision เข้าใจง่าย
- ไม่เกิดปัญหาตารางเต็มแบบทันที
- ลบข้อมูลง่ายกว่าวิธี probing
ข้อเสีย
- ใช้หน่วยความจำเพิ่มจาก list/node
- ถ้า bucket กระจุกมาก ความเร็วตก
9. วิธีที่ 2: Open Addressing คืออะไร
Open Addressing คือการเก็บข้อมูลทั้งหมดไว้ในตารางหลักเดียวกัน ถ้าชนกันจะวิ่งหา slot ว่างตามกฎ probing
10. แนวคิดหลักของ Open Addressing
- คำนวณ index เริ่มต้น
- ถ้าช่องไม่ว่าง ให้ลองช่องใหม่ตามสูตร probing
- ทำซ้ำจนเจอช่องว่างหรือเจอ key เป้าหมาย
11. Linear Probing คืออะไร พร้อมตัวอย่าง
Linear Probing คือการเลื่อนทีละ 1 ช่อง: i, i+1, i+2, ... (วน mod ขนาดตาราง)
step-by-step แบบเห็นภาพ
12. Quadratic Probing คืออะไร พร้อมอธิบายแนวคิด
Quadratic Probing จะกระโดดด้วยระยะกำลังสอง เช่น +1^2, +2^2, +3^2 ช่วยลดการกระจุกแบบต่อเนื่องเมื่อเทียบกับ linear probing
13. Double Hashing คืออะไร พร้อมอธิบายแนวคิด
Double Hashing ใช้ hash function ที่สองเพื่อกำหนดระยะกระโดด ทำให้ pattern การชนซ้ำลดลงและกระจายตำแหน่งได้ดีขึ้น
14. ข้อดีข้อเสียของ Open Addressing
ข้อดี
- ไม่ต้องมี list เพิ่มต่อ bucket
- โครงสร้างข้อมูลเก็บในอาเรย์เดียว
ข้อเสีย
- เมื่อ load factor สูง ประสิทธิภาพลดลงเร็ว
- การลบซับซ้อนกว่า ต้องจัดการ tombstone
- อาจเกิด clustering ได้
15. เปรียบเทียบ Chaining vs Open Addressing
| หัวข้อ | Chaining | Open Addressing |
|---|---|---|
| ที่เก็บข้อมูล | list ในแต่ละ bucket | ตารางหลักเดียว |
| การลบ | ตรงไปตรงมา | ต้องระวัง tombstone |
| เมื่อชนเยอะ | list ยาวขึ้น | probe ยาวขึ้น |
16. Pseudocode แบบพื้นฐาน
insert/search แบบ list ใน bucket
insert/search แบบ open addressing
17. ตัวอย่างโค้ด JavaScript
โครงสร้างพื้นฐานสำหรับจัดการ collision ด้วย chaining
โครงสร้างพื้นฐานสำหรับ open addressing แบบ linear probing
18. Time Complexity แบบภาพรวม
| วิธี | Average | Worst |
|---|---|---|
| Chaining | O(1) | O(n) |
| Open Addressing | O(1) | O(n) |
หมายเหตุ: ค่าเฉลี่ยเร็วเมื่อ hash function กระจายดีและ load factor ไม่สูงเกินไป
19. สรุปว่าควรเลือกใช้แบบไหนในภาพรวม
ถ้าต้องการแนวคิดตรงไปตรงมาและลบข้อมูลง่าย Chaining มักเริ่มต้นได้ง่าย แต่ถ้าต้องการเก็บในอาเรย์เดียวและควบคุมหน่วยความจำแบบต่อเนื่อง Open Addressing ก็เหมาะ
20. สรุปท้ายบท
collision เป็นเรื่องปกติของ Hash Table สิ่งสำคัญคือเลือกกลยุทธ์จัดการที่เหมาะกับงาน และควบคุมการกระจายข้อมูลให้ดี
สูตรจำง่าย: collision เกิดได้เสมอ -> ต้องมี policy จัดการ (Chaining/Open Addressing)
21. แบบฝึกหัด 3 ข้อ useplaygound
ข้อ 1: ระบุ collision จากข้อมูลที่กำหนด
ให้ hash(key) % 8 ของ key 6 ค่า แล้วหาว่าคู่ไหนชนกัน
แนวเฉลยย่อ: คำนวณ index ทีละ key แล้วจัดกลุ่มตาม index ที่ซ้ำ
ข้อ 2: จำลอง Chaining ด้วย array of arrays
เขียน insert และ search แบบง่าย แล้วทดสอบ key ที่ชนกัน
แนวเฉลยย่อ: เก็บแต่ละ bucket เป็น list และวนหา key ใน bucket เดียวกัน
ข้อ 3: จำลอง Linear Probing
เขียน insert แบบชนแล้วเลื่อนไปช่องถัดไปจนกว่าจะว่าง
แนวเฉลยย่อ: ใช้ while + (index + 1) % size และหยุดเมื่อกลับถึงจุดเริ่ม
ภาพประกอบที่ต้องมี
ภาพ 1: key หลายตัวชนที่ index เดียวกัน
ภาพ 2: Chaining ใน bucket เดียวมีหลาย node
ภาพ 3: Open Addressing วิ่งหา slot ว่าง
ภาพ 4: เปรียบเทียบ Chaining กับ Open Addressing