ปูพื้นฐาน Graphs: เครือข่ายและความเชื่อมโยง เบื้องหลัง Social Network และ Google Maps

1. 🎯 ตอนที่ 14: ปูพื้นฐาน Graphs (เครือข่ายและความเชื่อมโยง)
2. 📖 เปิดฉาก (The Hook)
น้องๆ เคยสงสัยไหมครับว่า Google Maps รู้ได้อย่างไรว่าทางไหนคือ “เส้นทางที่สั้นที่สุด” หรือ “เร็วที่สุด” ฝ่าดงรถติดไปถึงที่ทำงาน? หรือเวลาที่เราเล่น Facebook, LinkedIn แล้วจู่ๆ ระบบก็เด้งขึ้นมาว่า “People You May Know” (คนที่คุณอาจรู้จัก) แถมยังแม่นซะด้วย! ระบบพวกนี้มันรู้ความสัมพันธ์ที่ซับซ้อนโยงใยกันเป็นใยแมงมุมขนาดนี้ได้อย่างไร?
คำตอบไม่ได้มาจากเวทมนตร์ครับ แต่มาจากโครงสร้างข้อมูลที่ทรงอิทธิพลที่สุดตัวหนึ่งในโลกของวิทยาการคอมพิวเตอร์ นั่นคือ Graph (กราฟ)! ในขณะที่ Array หรือ Linked List เก็บข้อมูลเป็นเส้นตรง และ Tree เก็บข้อมูลแบบลำดับชั้น (Hierarchy) แต่ Graph เกิดมาเพื่อจำลอง “เครือข่ายและความสัมพันธ์” ที่ไม่มีจุดเริ่มต้นหรือจุดสิ้นสุดตายตัว วันนี้พี่จะพาไปปูพื้นฐานโครงสร้างข้อมูลตัวนี้กันครับ รับรองว่าถ้าน้องๆ เข้าใจ Graph โลกของการเขียนโปรแกรมจะไม่เหมือนเดิมอีกต่อไป!
3. 🧠 แก่นวิชา (Core Concepts)
จากคัมภีร์ The Algorithm Design Manual และตำรา Data Structures ระดับโลก Graph $G = (V, E)$ ประกอบไปด้วยองค์ประกอบหลัก 2 ส่วนครับ:
- Vertices (หรือ Nodes): จุดยอดที่ใช้เป็นตัวแทนของ “สิ่งของ” หรือ “เอนทิตี” (Entities) เช่น ใน Facebook ตัว Vertex ก็คือโปรไฟล์ของพวกเราแต่ละคน หรือใน Google Maps มันก็คือพิกัดของสถานที่หรือทางแยกต่างๆ
- Edges (หรือ Links): เส้นเชื่อมที่ใช้บอก “ความสัมพันธ์” ระหว่าง Vertices เช่น เส้นเชื่อมบอกว่านาย A เป็นเพื่อนกับนาย B หรือเส้นถนนที่เชื่อมระหว่างสองสี่แยก
และด้วยความที่โลกเรามีความสัมพันธ์หลายรูปแบบ Graph จึงถูกแบ่งสายพันธุ์ย่อย (Flavors of Graphs) ออกไปอีก ดังนี้ครับ:
- Directed vs. Undirected Graph (มีทิศทาง vs ไม่มีทิศทาง):
- Undirected (ไม่มีทิศทาง): ความสัมพันธ์แบบไปกลับ เช่น การเป็นเพื่อนใน Facebook ถ้าน้องเป็นเพื่อนกับพี่ พี่ก็ต้องเป็นเพื่อนกับน้อง (เส้นเชื่อมวิ่งได้สองทาง)
- Directed หรือ Digraph (มีทิศทาง): ความสัมพันธ์แบบวันเวย์ เช่น การกด Follow ใน Instagram หรือ Twitter น้องตามพี่ได้ แต่พี่ไม่จำเป็นต้องตามน้องกลับ (เส้นเชื่อมมีหัวลูกศรชี้บอกทิศทาง)
- Weighted vs. Unweighted Graph (มีน้ำหนัก vs ไม่มีน้ำหนัก):
- Unweighted (ไม่มีน้ำหนัก): ทุกเส้นเชื่อมมีค่าเท่ากันหมด เช่น การนับจำนวนคนรู้จัก (Hop) ว่าห่างกันกี่ช่วงตัว
- Weighted (มีน้ำหนัก หรือ Network): เส้นเชื่อมแต่ละเส้นมี “ต้นทุน” หรือ “ระยะทาง” กำกับไว้ เช่น ถนนแต่ละเส้นใน Google Maps มีระยะทาง (กิโลเมตร) หรือเวลาที่ใช้เดินทาง (นาที) ไม่เท่ากัน เส้นที่มีรถติดก็จะมี Weight สูงกว่านั่นเอง

4. 💻 ร่ายมนต์โค้ด (Show me the Code)
การเก็บข้อมูล Graph ในหน่วยความจำ (Memory) มีหลายท่า แต่ท่าที่ฮิตที่สุดและประหยัดพื้นที่สำหรับกราฟทั่วๆ ไป คือการใช้ Adjacency List (รายการความติดกัน) ครับ ในภาษา Python เราสามารถใช้ Dictionary จับคู่ระหว่าง Vertex และลิสต์ของเพื่อนบ้าน (Neighbors) ได้อย่างสวยงาม มาลองสร้าง Social Network จำลองกันครับ!
# จำลอง Social Network ด้วย Adjacency List สำหรับ Undirected Graph
# Key คือชื่อคน (Vertex) และ Value คือรายชื่อเพื่อน (Adjacent Vertices)
social_network = {
'Alice': ['Bob', 'Cynthia', 'Diana'],
'Bob': ['Alice', 'Cynthia', 'Fred'],
'Cynthia': ['Alice', 'Bob'],
'Diana': ['Alice', 'Fred'],
'Fred': ['Bob', 'Diana'],
'Elise': [] # Elise สายสันโดษ ไม่มีเพื่อนเลย (Isolated vertex)
}
# ฟังก์ชันง่ายๆ เพื่อหาว่า A และ B เป็นเพื่อนกันโดยตรงหรือไม่
def are_they_friends(graph, person1, person2):
# เช็คแบบ O(1) ทางทฤษฎี (หรือ O(V) ใน worst case ของลิสต์) ว่าคนนึงอยู่ในลิสต์ของอีกคนไหม
if person2 in graph.get(person1, []):
return True
return False
# ----- ลองวิชา -----
print("Alice เป็นเพื่อนกับ Bob หรือไม่?", are_they_friends(social_network, 'Alice', 'Bob'))
# Output: True
print("Alice เป็นเพื่อนกับ Fred หรือไม่?", are_they_friends(social_network, 'Alice', 'Fred'))
# Output: False (แต่เขาสามารถรู้จักกันผ่าน Bob หรือ Diana ได้นะ!)5. 🛡️ เคล็ดลับจากคัมภีร์ลับ (Under the Hood / Pro-Tips)
ถ้าน้องๆ ไปสัมภาษณ์งานบริษัท Tech ใหญ่ๆ คำถามปราบเซียนที่จะเจอคือ “เมื่อไหร่ควรใช้ Adjacency List และเมื่อไหร่ควรใช้ Adjacency Matrix?”
จากคัมภีร์ Data Structures and Algorithms มีกฎเหล็กในการตัดสินใจดังนี้ครับ:
- Adjacency Matrix: คือการสร้าง Array 2 มิติ ขนาด $V \times V$ (ตารางไขว้)
- ข้อดี: ตรวจสอบว่ามีเส้นเชื่อมไหมได้ไวแสงระดับ $O(1)$ แค่เช็คพิกัด
matrix[u][v] - ข้อเสีย: กินพื้นที่ Memory มหาศาลระดับ $O(V^2)$ สมมติว่ามีผู้ใช้ 1 ล้านคน น้องต้องสร้างตาราง 1 ล้าน x 1 ล้านช่อง! (พังแน่นอน)
- เหมาะกับ: Dense Graphs (กราฟหนาแน่น) ที่ทุกๆ โหนดเชื่อมกันแทบจะหมด
- ข้อดี: ตรวจสอบว่ามีเส้นเชื่อมไหมได้ไวแสงระดับ $O(1)$ แค่เช็คพิกัด
- Adjacency List (แบบในโค้ดตัวอย่าง):
- ข้อดี: กินพื้นที่ Memory น้อยมากๆ แค่ $O(V + E)$ ตามจำนวนคนและเส้นเชื่อมที่มีอยู่จริง
- เหมาะกับ: Sparse Graphs (กราฟเบาบาง) ซึ่งในโลกความเป็นจริง โครงสร้างส่วนใหญ่เป็นแบบนี้ครับ! เช่น ต่อให้ Facebook มีคนเป็นพันล้านคน แต่คนนึงก็มีเพื่อนเฉลี่ยแค่หลักร้อยถึงพันคนเท่านั้น การใช้ Adjacency List จึงเป็น Best Practice สำหรับโจทย์ส่วนใหญ่ครับ
6. 🏁 บทสรุป (To be continued…)
Graph คือกระบวนทัศน์ขั้นสูงที่ช่วยให้เราจำลองโลกความเป็นจริงลงในคอมพิวเตอร์ได้อย่างไร้ขีดจำกัด ไม่ว่าจะเป็นวงจรไฟฟ้า, ระบบแผนที่, หรือ โครงข่ายอินเทอร์เน็ต แค่น้องเข้าใจนิยามของ Vertices, Edges, Directed และ Weighted ก็ถือว่ามีชัยไปกว่าครึ่งแล้วครับ!
แต่การมีแค่แผนที่เฉยๆ ก็คงหาทางออกไม่ได้จริงไหมครับ? ในตอนหน้า พี่จะพาน้องๆ ไปพบกับอัลกอริทึม “นักสำรวจ” อย่าง Breadth-First Search (BFS) และ Depth-First Search (DFS) ที่จะมาวิ่งลุยไปตามเส้นทางต่างๆ ใน Graph เพื่อหาคำตอบว่า “มีทางไปถึงเป้าหมายหรือไม่” และ “เส้นทางไหนสั้นที่สุด” เตรียมตัวให้พร้อม แล้วพบกันครับ!
ต้องการที่ปรึกษาด้านการออกแบบ System Architecture และพัฒนาระบบซอฟต์แวร์สเกลใหญ่ให้กับองค์กรของคุณ? ทีมงาน WP Solution พร้อมให้บริการออกแบบและพัฒนาซอฟต์แวร์แบบครบวงจร ดูรายละเอียดบริการของเราได้ที่: www.wpsolution2017.com หรือพูดคุยปรึกษาเบื้องต้นได้ที่ Line: wisit.p