1 / 41

บทที่ 10 โครงสร้างข้อมูลกราฟ กราฟ

บทที่ 10 โครงสร้างข้อมูลกราฟ กราฟ

cissy
Download Presentation

บทที่ 10 โครงสร้างข้อมูลกราฟ กราฟ

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. บทที่ 10 โครงสร้างข้อมูลกราฟ กราฟ กราฟ (Graph) เป็นโครงสร้างข้อมูลไม่เป็นเชิงเส้น (Nonlinear Data Structure) มีความแตกต่างจากโครงสร้างข้อมูลทรีในบทที่ผ่านมา แต่เป็นลักษณะพิเศษแบบหนี่งของกราฟโดยทรีเป็นกราฟอะไซคลิกที่ไม่มีการวนลูปและการวนถอยกลับ เป็นกราฟเชื่อมกันที่มีเพียงเอจเดียวระหว่างสองโหนด

  2. กราฟมีลักษณะเป็นเซ็ตของจุด (Point) และเซ็ตของเส้น (Line) ซึ่งแต่ละเส้นทำหน้าที่เชื่อมต่อจุดเข้าด้วยกัน แต่ละจุดเรียกว่าโหนด (Node) ของกราฟและเส้นเรียกว่าเอจ (Edge)บางครั้งเอจจะเรียกว่าอาร์ค (Arc) และโหนดเรียกว่าเวอร์ทิค (Vertice) โดยกำหนดให้กราฟ G มีเซ็ตของโหนดเป็น VG และเซ็ตของเอจเป็น EG  เช่นในรูปที่ 10.1 VG ={a,b,c,d} และ EG= {1,2,3,4,5,6,7,8} จำนวนสมาชิกที่มีใน VG  เรียกว่าออเดอร์ (Order) ของกราฟ ถ้าออเดอร์เท่ากับ 0 คือ กราฟไม่มีสมาชิกเรียกว่านัลกราฟ (Null Graph)

  3. รูปที่ 10.1ตัวอย่างกราฟที่มีจำนวนสมาชิกออเดอร์เท่ากับ 4 เอจของแต่ละโหนดจะพิจารณาจากการเชื่อมต่อกัน เช่น เอจ 4 เชื่อมโหนด c กับ d และกำหนดเป็น Path (c,d) โดยตำแหน่งของสมาชิกไม่มีความสำคัญ ดังนั้น กราฟในรูปที่ 10.1 จึงเท่ากับกราฟในรูปที่ 10.2 ต่อไปนี้

  4. รูปที่ 10.2ตัวอย่างกราฟที่เท่ากับกราฟในรูปที่ 10.1 โดยตำแหน่งของโหนดที่ต่างกัน • ในการเชื่อมต่อกันระหว่างสองโหนดอาจมีได้หลาย ๆ เอจ เช่น เอจ 5, 6, และ 7 ซึ่งเป็น Path (b,d)  ทั้งหมด เช่นกันไม่มีเอจที่เป็น  Path(a,d) บางเอจเชื่อมต่อกันเพียงโหนดเดียวกับตัวเองคือเอจ 8 ที่เป็น Path(a,a) แบบวนลูป

  5. รูปที่ 10.3 ตัวอย่างกราฟเรียบง่าย 1.  กราฟ G จะเป็นกราฟเรียบง่าย (Simple Graph) ในรูปที่ 10.3 ต้องเป็นไปตามเงื่อนไข ดังนี้ 1.1   ต้องไม่มีการวนลูปของเอจเกิดขึ้นใน EG  หรือมี Path(V,V) 1.2   ต้องไม่มีเอจมากกว่าหนึ่งเชี่อมต่อกันระหว่างสองโหนด

  6. รูปที่ 10.4ตัวอย่างกราฟที่ไม่ต่อกัน 2. กราฟ G ถ้าไม่ใช่กราฟเรียบง่ายเรียกว่า มัลติกราฟ (Multigraph) 3. กราฟ G จะเป็นกราฟต่อกัน (Connected Graph) ก็ต่อเมื่อไม่สามารถแยกออกเป็นสองกราฟ ยกเว้นมีการตัดเอจใดเอจหนึ่งออกไป ส่วนกราฟที่ไม่ต่อกันดังวนรูปที่ 10.4 มีโหนด f และ h ไม่ต่อกับโหนดอื่น

  7. เส้นทาง เส้นทางในกราฟ (Path) เป็นการจัดลำดับของเอจที่มีตั้งแต่หนึ่งหรือมากกว่าทำการเชื่อมต่อระหว่างสองโหนด ซึ่งกำหนดเป็น P(Vi,Vj) คือ เส้นทางการเชื่อมระหว่างโหนด Vi กับVjและถ้า P(Vi,Vj) มีในกราฟก็จะต้องอยู่ใน EG  ดังนั้น ลำดับของเอจจะอยู่ในรูปแบบต่อไปนี้                                P(Vi,Vj) = (Vi,X1) (X1,X2) . . . (Xn-1,Xn) (Xn,Vj) และจะได้ความยาวของเส้นทางเป็นจำนวนเอจที่ประกอบรวมกัน จากกราฟเรียบง่ายในรูปที่ 10.3 จะได้เส้นทางระหว่างโหนด b กับ d ดังนี้ เส้นทาง 1 P(b,d) = (b,c)(c,d)                                   ความยาวเท่ากับ 2 เส้นทาง 2 P(b,d) = (b,c)(c,b)(b,c)(c,d)                    ความยาวเท่ากับ 4 เส้นทาง 3 P(b,d) = (b,d)                                          ความยาวเท่ากับ 1 เส้นทาง 4 P(b,d) = (b,c)(c,b)(b,d)                           ความยาวเท่ากับ 3

  8. โดยทั่วไปเส้นทางที่ต้องการและสนใจเลือกใช้คือ เส้นทางที่วิ่งผ่านโหนดเพียงครั้งเดียวเท่านั้น ก็จะได้เฉพาะเส้นทาง 1 กับ 3 ส่วนเส้นทาง 2 มีการวิ่งผ่านโหนด b และ c สองครั้งและเส้นทาง 4 วิ่งผ่านโหนด b สองครั้ง นอกจากนี้ยังสนใจเฉพาะเอจที่ถูกวิ่งผ่านเพียงครั้งเดียวเช่นกัน เนื่องจากช่วยให้อัลกอริทึมไม้ต้องล่าช้าที่ต้องกลับไปทำงานในเส้นทางเดิม

  9. ไซเคิล เส้นทางที่เป็นไซเคิล (Cycle) หรือการวนกลับจะมีลักษณะที่เป็นไปตามเงื่อนไขต่อไปนี้ 1.       จะต้องไม่เอจมากกว่าหนึ่งอยู่ในลำดับของเอจในเส้นทางนั้น 2.       โหนดเริ่มต้นของเส้นทางจะต้องเป็นโหนดสุดท้ายของเส้นทางนั้นด้วย คือ P(V,V) เส้นทางที่เป็นไซเคิลจะต้องกลับมายังจุดที่เริ่มต้นเสมอ จากกราฟในรูปที่ 10.2 จะมีเส้นทางที่เป็นไซเคิล ดังนี้

  10. เส้นทาง 1 P(a,a) = (a,a) เส้นทาง 2 P(b,b) = (b,c)(c,b) เส้นทาง 3 P(b,b) = (b,c)(c,d)(d,b) เส้นทาง 4 P(d,d) = (d,b)(b,c)(c,d) เส้นทาง 5 P(d,d) = (d,b)(b,d) เมื่อใดที่กราฟไม่มีเส้นทางที่เป็นไซเคิลเรียกว่าอะไซคลิก (Acyclic) ดังรูปที่ ข้างบนนี้ซึ่งเป็นกราฟอะไซคลิกรูป (a) และรูป (b)

  11. กราฟทิศทาง ลักษณะเฉพาะที่เพิ่มเข้ามาในโครงสร้างข้อมูลกราฟทั่วไปได้เป็นกราฟทิศทาง(Directed Graph) ซึ่งใช้หัวลูกศรเป็นตัวกำหนดทิศทางให้แต่ละเอจในกราฟ ดังในรูปที่ 10.6

  12. กราฟทิศทางจะมีดีกรีเข้า (In-Degree) เป็นจำนวนเอจที่ชี้เข้ามาสิ้นสุดที่โหนดและมีดีกรีออก (Out-Degree) เป็นจำนวนเอจที่ชี้ออกจากโหนด ดีกรีของโหนดใดโหนดหนึ่ง คือ ผลรวมของดีกรีเข้ากับดีกรีออก จากรูปที่ 10.6 จะได้ดีกรีของแต่ละโหนดดังนี้  In-Degree (a) = 1                Out-Degree (a) = 2                    Degree (a) = 3 In-Degree (b) = 4                Out-Degree (b) = 2                   Degree (b) = 6 In-Degree (c) = 1                Out-Degree (c) = 2                    Degree (c) = 3 In-Degree (d) = 2                Out-Degree (d) = 2                    Degree (d) = 4

  13. การสร้างกราฟใช้งาน โดยปกติภาษาเขียนโปรแกรมมีการสร้างโครงสร้างข้อมูลให้ใช้งานได้ทันที (Build-in Type) แต่ไม่มีกราฟรวมอยู่ด้วย ดังนั้น ผู้เขียนโปรแกรมที่ต้องการสร้างกราฟขึ้นมาใช้งานจะมีการนำโครงสร้างข้อมูลอื่นมาใช้เป็นกราฟ โดยมีอยู่ 3 แนวทางที่นำมาใช้ คือ 1.       ใช้แมตทริกติดกัน (Adjacency Matrix)  หรืออาร์เรย์สองมิติกำหนดเป็นกราฟ 2.       ใช้ลิสต์แบบไดเร็กทอรี่โหนด (Node Directory) กำหนดเป็นกราฟ 3.       ใช้มัลติลิสต์ (Multi-List) กำหนดเป็นกราฟ

  14. กราฟแบบแมตทริกติดกัน ให้กราฟ G มีเซ็ตของโหนดเป็น VG และเซ็ตของเอจเป็น EG โดยกราฟมีออเดอร์เท่ากับ N ซึ่ง  N  >= 1 แนวทางหนึ่งในการกำหนดเป็นกราฟโดยใช้แมตทริกติดกัน (Adjacency  Matrix) เป็นอาร์เรย์ N-ต่อ-N เมื่อให้เป็นอาร์เรย์ A จะได้ว่า หมายความว่า หากมีเอจที่เชื่อมต่อกันระหว่างโหนดiกับ j ก็จะได้ A(i,j) = 1 ไม่เช่นนั้นมีค่าเป็น 0จากรูปที่ 10.7เป็นกราฟไม่มีทิศทางในรูป (a) เมื่อนำมาเขียนเป็นแมตทริกติดกันได้เป็นรูป (b)

  15. รูปที่ 10.7ตัวอย่างกราฟไม่มีทิศทางและรูปแบบที่เป็นแมตทริกติดกัน หากเป็นกราฟทิศทาง แต่ละเอจจะมีโหนดเริ่มต้นและไปสิ้นสุดที่โหนดอื่น จะได้ว่า Edge(Vi,Vj) เป็นทิศทางจากโหนด Vi  ไปยังโหนดV j จากรูปที่ 10.8 ซึ่งเป็นกราฟทิศทางในรูป (a) นำมาเขียนเป็นแมตทริกติดกันได้เป็นรูป (b)

  16. รูปที่ 10.8ตัวอย่างกราฟทิศทางและรูปแบบที่เป็นแมตทริกติดกัน เอจมีน้ำหนัก มีการนำกราฟแบบแมตทริกติดกันมาใช้ในแอปพลิเคชั่น เช่น กราฟในรูปที่ 10.9 ซึ่ง เป็นการใช้งานในระบบสารสนเทศของการจัดส่งสินค้า กราฟดังกล่าวประกอบด้วยเอจมีน้ำหนัก (Weighted Edge) โดยให้โหนดแทนความหมายของเมือง (City) และเอจแทนความหมายถึงเส้นทางในกานส่งสินค้าระหว่างเมือง แต่ละเอจมีการกำหนดระยะทางที่เชื่อมต่อกันระหว่างเมือง

  17. ดังนั้น ในแมตทริกติดกันแทนที่จะใช้ค่า 1 กับ 0 หรือบิตแมตทริก (Bit Matrix) เหมือนที่ผ่านมา ก็เปลี่ยนมาใช้เป็นเอจมีน้ำหนักแทนได้เป็นรูปที่ 10.10 และแต่ละโหนดหรือเมืองจะใช้หมายเลขแทน

  18. 1 = ABQ ,2 = CVG ,3 = DFW ,4 = DNV ,5 = ELP ,6 = HST 7 = KNC ,8 = LAX,9 = NSH ,10 = NOR ,11 = ORD ,12 = PHX ,13 = SEA ,14 = SFO ,15 = SLC,16 = SPK

  19. เอจมีน้ำหนักจะถูกนำมาใช้งานบ่อย เช่น แอปพลิเคชั่นการขนส่ง (Transportation Application) ซึ่งน้ำหนักของเอจ หมายถึง ระยะทาง (Distance) ดังที่ผ่านมา แอปพลิเคชั่นการไหล (Flow Application) ซึ่งน้ำหนัก หมายถึง ปริมาณความจุ (Capacity) โดยให้โหนดของกราฟ คือ แกลลอน (Gallon) ที่มีท่อส่งในปริมาณความจุต่อวินาทีระหว่างโหนด หรือในระบบสื่อสารข้อมูลที่มีปริมาณการส่งเป็นบิตต่อวินาทีระหว่างสถานี หรือในระบบเครือข่าย (Network) ที่ให้น้ำหนัก หมายถึง เวลาที่ต้องใช้ในการทำงานกิจกรรมคือเอจให้เสร็จสิ้น แต่ละโหนดจะเป็นเหตุการณ์ (Event) ให้ทำกิจกรรม เมื่อเสร็จสิ้นลงก็ไปยังโหนดถัดไป ลักษณะดังกล่าวนำมาใช้กับระบบการบริหารจัดการโครงการ (Project Management System)

  20. กราฟแบบไดเร็กทอรี่โหนดกราฟแบบไดเร็กทอรี่โหนด เทคนิคการใช้แมตทริกติดกันเป็นกราฟมีความต้องการเก็บข้อมูลเกี่ยวกับเอจครบทุกรูปแบบระหว่างโหนดที่เป็นไปได้ เมื่อกราฟมี N โหนดความเป็นไปได้จะมีเอจเชื่อมกันเท่ากับN2  ซึ่งทำให้มีค่า 0 เป็นจำนวนมาก ดังนั้น การนำลิ้งค์ลิสต์มาใช้เป็นกราฟจึงมีความเหมาะสมกว่า ซึ่งจะมีเฉพาะเอจที่เชื่อมต่อกันเท่านั้น กานใช้โครงสร้างลิ้งค์ลิสต์เป็นกราฟจะมี 2 รูปแบบ คือ แบบไดเร็กทอรี่โหนด (Node Directory) และแบบมัลติลิสต์(Multi-List) ในหัวข้อถัดไป กราฟแบบไดเร็กทอรี่โหนดประกอบด้วยสองส่วน คือ ไดเร็กทอรี่ (Directory) และเซ็ตของลิ้งค์ลิสต์ แต่ละค่าในไดเร็กทอรี่มีสำหรับแต่ละโหนดที่อยู่ในกราฟ ค่าในไดเร็กทอรี่สำหรับโหนดiจะชี้ไปยังลิ้งค์ลิสต์ที่เชื่อมต่อไปยังโหนดที่เชื่อมต่อกับโหนดiลิ้งค์ลิสต์เป็นเรคคอร์ดประกอบด้วยสองเขตข้อมูล คือ ค่าความแตกต่างของแต่ละโหนด (Node Identifier) เป็นหมายเลขโหนดและตัวเชื่อมชี้ไปยังสมาชิกถัดไปในลิสต์ ดังนั้น ไดเร็กทอรี่จะหมายถึงโหนดส่วนลิ้งค์ลิสต์หมายถึงเอจ

  21. จะได้ว่ากราฟไม่มีทิศทางที่มีออเดอร์เท่ากับ N และมีเอจเท่ากับ E ค่าที่มีในไดเร็กทอรี่เท่ากับ N และค่าในลิ้งค์ลิสต์เท่ากับ 2*Eเมื่อใช้เป็นกราฟทิศทาง จากรูปที่ 10.8 นำมาเขียนเป็นแบบไดเร็กทอรี่โหนดก็จะได้เป็นรูปที่ 10.12 ซึ่งกราฟทิศทางที่มีออเดอร์เท่ากับ N และเอจเท่ากับ E ค่าที่มีในไดเร็กทอรี่เท่ากับ N และค่าในลิ้งค์ลิสต์เท่ากับ E

  22. เอจมีน้ำหนัก การใช้กราฟแบบไดเร็กทอรี่โหนดกับเอจมีน้ำหนัก โครงสร้างข้อมูลจะต้องมีการจัดเก็บน้ำหนักของเอจ ดังในตัวอย่างกราฟทิศทางในรูปที่ 10.13 ซึ่งแต่ละโหนดเปลี่ยนเป็นรูปวงกลมที่มีชื่อกำหนดไว้ภายใน แต่ละเอจมีน้ำหนักกำหนดเป็นกราฟแสดงกิจกรรมเป็นตัวเลข โดยแต่ละโหนดเป็นเหตุการณ์ (Event) และแต่ละเอจเป็นกิจกรรมที่ต้องทำซึ่งมีน้ำหนักที่หมายถึงเวลากราฟชนิดนี้จะนำมาใช้ในการบริหารจัดการโครงการ

  23. เมื่อนำมาเขียนเป็นแบบไดเร็กทอรี่โหนดจะได้เป็นรูปที่ 10.14 โดยแต่ละเรคคอร์ดของเอจประกอบด้วยค่าความแตกต่างหรือหมายเลขของแต่ละโหนดปลายทาง น้ำหนักของเอจและตัวเชื่อมที่ชี้ไปยังเอจถัดไป

  24. กราฟแบบมัลติลิสต์ ในโครงสร้างกราฟแบบมัลติลิสต์ประกอบด้วยสองส่วนคือ ไดเร็กทอรี่ของโหนดและเซ็ตลิ้งค์ลิสต์ของเอจ แต่ละค่าในไดเร็กทอรี่คือแต่ละโหนดที่อยู่ในกราฟ ดังนั้น ค่าในไดเร็กทอรี่สำหรับโหนดiจะชี้ไปยังลิ้งค์ลิสต์ที่เชื่อมต่อไปยังโหนดที่เชื่อมติดกับโหนดiลิ้งค์ลิสต์เป็นเรคคอร์ดประกอบด้วยสองลิสต์ติดกันใช้เป็นโหนดหัวและโหนดท้ายของเอจ ดังในรูปที่ 10.15 เป็นโครงสร้างของแต่ละเอจที่มี Edge(Vi,Vj)

  25. แอปพลิเคชั่นที่เขียนขึ้นมาเมื่อใช้งานกราฟส่วนใหญ่ต้องเข้าไปเรียกใช้งานในแต่ละโหนด เช่น การพิมพ์รายการกิจกรรมในระบบการบริหารจัดการโครงการ การแสดงผลระยะทางระหว่างเมือง เทคนิคพื้นฐานการวิ่งตามเส้นทางในกราฟ (Graph Traversal) ที่จะกล่าวถึง คือ การวิ่งตามแนวกว้างก่อน (Breadth – first) และการวิ่งตามแนวลึกก่อน (Depth – first) การวิ่งตามเส้นทางมีสิ่งที่ต้องระวัง คือ การวิ่งไปถึงแต่ละโหนดควรมีเพียงครั้งเดียว การวิ่งซ้ำโหนดเดิมทำให้การทำงานและผลที่ได้เกิดขึ้นซ้ำจากการวิ่งย้อนตามเส้นทางที่เคยผ่านมาแล้ว และมีหลายเส้นทางที่เชื่อมต่อระหว่างสองโหนด การเขียนอัลกอริทึมการวิ่งตามเส้นทางในกราฟจะใช้เครื่องหมายหรือตัวมาร์ก (Mark) บอกให้ทราบว่ามีการวิ่งมายังโหนดนี้แล้ว โดยก่อนหน้านี้จะถูกมาร์กว่ายังไม่วิ่งมา หรือเปลี่ยนมาใช้ตัวมาร์กกับเอจแทน ดังนั้น เอจที่ผ่านไปแล้วจะไม่ถูกรวมกับเอจอื่น ๆ ที่เหลือ เครื่องหมายหรือตัวมาร์กจะใช้เป็นมาร์กบิต (Mark Bit)   เก็บไว้ในแต่ละโหนดหรือเอจ

  26. การวิ่งตามแนวกว้างก่อนการวิ่งตามแนวกว้างก่อน การวิ่งตามเส้นทางในกราฟตามแนวกว้างก่อน (Breath – first Traversal) หรือการค้นหาตามแนวกว้างก่อน (Breath – first Traversal) เริ่มด้วยการเลือกมาหนึ่งโหนดเป็นตำแหน่งเริ่มต้นและทำเครื่องหมายว่าวิ่งผ่านมาแล้ว จากนั้นวิ่งไปยังโหนดทุกโหนดที่ติดกับโหนดนี้และยังไม่วิ่งผ่านและทำเครื่องหมาย ทำเช่นนี้จะกระทั่งวิ่งผ่านทุก ๆ โหนดที่มีอยู่ในกราฟ การวิ่งตามแนวกว้างในกราฟจากรูปที่ 10.13 ผลจากการวิ่งไปยังแต่ละโหนดจะมีลำดับเป็น 1,2,3,4,5,6,7,8 หรือมีลำดับเป็น 1,3,2,6,5,4,7,8 ก็ได้ ขึ้นอยู่กับการเลือกโหนดที่จะวิ่งผ่านทางด้านซ้ายหรือขวาก่อน อัลกอริทึมการวิ่งตามเส้นทางในแนวกว้างก่อนจะใช้โครงสร้างข้อมูลคิวเพื่อเก็บโหนดที่วิ่งผ่านไปแล้วในแต่ละระดับของกราฟ แต่ละโหนดที่เก็บในคิวจะใช้สำหรับวิ่งไปยังโหนดติดกันที่ยังไม่ได้วิ่งไป ทำจนวิ่งผ่านทุกโหนดในกราฟและสิ้นสุดลงเมื่อคิวว่าง อัลกอริทึมการวิ่งตามเส้นทางในแนวกว้างก่อนดังในตารางที่ 10.1

  27. ตารางที่ 10.1อัลกอริทึมการวิ่งตามเส้นทางในกราฟตามแนวกว้างก่อน 1.วิ่งผ่านไปยังโหนด N ให้เป็นโหนดแรกเพื่อเริ่มต้น และทำเครื่องหมาย Mark (N)2.สร้างคิวขึ้นมาและเก็บโหนดแรก Insert(N,Queue)3.ถ้าคิวยังไม่ว่างให้ทำดังนี้                3.1ทำการลบโหนด N ออกจากคิว Remove(Queue)                3.2สำหรับทุก ๆโหนด W ที่เชื่อมต่อกับโหนด N ให้ทำดังนี้                            a.ถ้าโหนด W ยังไม่ถูกวิ่งผ่าน                                    a.1ทำเครื่องหมายว่าโหนด W วิ่งผ่านแล้ว Mark (W)                                    a.2เก็บโหนด W ไว้ในคิว  Insert(W,Queue)ในการวิ่งตามเส้นทางในแนวกว้างก่อนมีการวิ่งผ่านโหนดที่เป็นระดับต่อระดับ (Level – by – Lavel) โดยแต่ละโหนดระดับเดียวกันจะถูกเก็บไว้ในคิวเพื่อกลับมาเรียกใช้งานได้หลังจากการทำงานในระดับนี้เสร็จสิ้นลง ต่อจากนั้นวิ่งไปยังโหนดระดับถัดไปที่เชื่อมต่อกับโหนดเหล่านี้ ลักษณะของอัลกอริทึมเป็นการทำงานที่วนซ้ำแบบเดิม (Iterative) ที่หัวข้อที่ 3 และ 4 เมื่อนำการวิ่งตามเส้นทางในแนวกว้างกับกราฟทิศทางในรูปที่ 10.17 จะมีขั้นตอนหรือระดับเป็นดังนี้

  28. รูปที่ 10.17ตัวอย่างกราฟทิศทางกับเส้นทางการวิ่ง  1.ในระดับแรกเริ่มต้นว่างผ่านที่โหนด A และเก็บในคิวได้ {A} A 2. ดึงโหนด A จากคิว เพื่อหาโหนดที่เชื่อมกันและวิ่งผ่านทุกโหนดพร้อมเก็บลงในคิวได้ {B,D,E} A,B,D,E    3.    ดึงโหนด B จากคิว เพื่อหาโหนดที่เชื่อมกันและวิ่งผ่านทุกโหนดพร้อมเก็บลงในคิวได้ {D,E,F} A,B,D,E,F

  29.        4.    ดึงโหนด D จากคิว เพื่อหาโหนดที่เชื่อมกันและวิ่งผ่านทุโหนดพร้อมเก็บลงในคิวได้ {E,F,C,H} A,B,D,E,F,C,H        5.    ดึงโหนด E จากคิว เพื่อหาโหนดที่เชื่อมกันคือ H ซึ่งวิ่งผ่านไปแล้ว ในคิวจะได้ {F,C,H} A,B,D,E,F,C,H    6.    ดึงโหนด F จากคิว เพื่อหาโหนดที่เชื่อมกันและวิ่งผ่านทุกโหนดพร้อมเก็บลงในคิวได้ {C,H,I,G} A,B,D,E,F,C,H,I,G

  30. เมื่อดึงโหนดที่เหลือในคิวเพื่อหาโหนดที่เชื่อมต่อกันจะพบแต่โหนดที่วิ่งผ่านไปแล้วและคิวว่างจึงจบการทำงาน ก็จะได้โหนดที่ถูกวิ่งผ่านเรียงตามลำดับในแนวกว้างก่อนคือA, B, D, E, F, C, H, I, G ถ้าให้โหนด B เริ่มต้นก่อน โหนดที่ถูกวิ่งผ่านเรียงตามลำดับในแนวกว้างก่อน คือ B, F, I, G, H, C, D • การวิ่งตามแนวลึกก่อน • ขณะที่การวิ่งตามเส้นทางในแนวกว้างก่อนมีการวิ่งผ่านโหนดเป็นระดับต่อระดับ แต่การวิ่งตามแนวเส้นทางในแนวลึกก่อน(Depth–first Traversal) หรือการค้นหาตามแนวลึกก่อน (Depth – first Search) จะเริ่มจากโหนดแรกวิ่งผ่านตามเส้นทางเพื่อไปยังโหนดสุดท้ายซึ่งไม่สามารถวิ่งต่อไปได้อีก จากนั้นถอยกลับเพื่อวิ่งผ่านต่อไปยังเส้นทางอื่นที่อยู่ติดกันในโหนดก่อนหน้านี้และวิ่งจนครบทุกโหนดในกราฟ การวิ่งตามแนวลึกในกราฟจากรูปที่ 10.13 ผลจากการวิ่งไปยังแต่ละโหนดจะมีลำดับเป็น 1,2,4,8,5,7,3,6 หรือมีลำดับเป็น 1,3,6,7,8. 2,5,4 ก็ได้ขึ้นกับการเลือกโหนดที่จะวิ่งผ่านทางด้านซ้ายหรือขวาก่อน

  31. ขณะที่อัลกอริทึมการวิ่งตามเส้นทางในแนวกว้างก่อนใช้การทำงานที่วนซ้ำแบบเดิม ส่วนการวิ่งตามเส้นทางในแนวลึกก่อนใช้การทำงานแบบเรียกตัวเองทำงานหรือรีเคอร์ซีฟ(Recursive) อัลกอริทึมการวิ่งตามเส้นทางในแนวลึกก่อนดังในตารางที่ 10.2 • ตาราง  10.2 อัลกอริทึมการวิ่งตามเส้นทางในกราฟตามแนวลึกก่อน • 1.วิ่งผ่านไปยังโหนด N ให้เป็นโหนดแรกเพื่อเริ่มต้น และทำเครื่องหมาย Mark(N)2.สำหรับทุก ๆโหนด W ที่เชื่อมต่อกับโหนด  N ให้ทำดังนี้        a.ถ้าโหนด W ยังไม่ถูกวิ่งผ่านให้เรียกอัลกอริทึมนี้ขึ้นมาทำงานใหม่กับโหนด W ซึ่งกำหนดเป็นโหนดแรกเพื่อเริ่มต้น • ในการวิ่งตามเส้นทางในแนวลึกก่อนมีการวิ่งผ่านโหนดแรก จากนั้นวิ่งต่อไปยังโหนดถัดไปที่เชื่อมต่อกันโดยการเรียกตัวเองทำงานใหม่ และมีการถอยกลับไปยังโหนดก่อนหน้านี้เมื่อไม่สามารถวิ่งลงต่อไปได้อีก การถอยกลับมาเพื่อวิ่งต่อไปได้ยังโหนดอื่นที่ยังไม่วิ่งผ่าน ซึ่งมีการนำสแตกมาใช้เก็บโหนดที่การทำงานผ่านไปแต่ยังไม่ได้วิ่งผ่าน เมื่อถอยกลับก็ดึงโหนดเหล่านี้มาใช้งาน เมื่อนำการวิ่งตามเส้นทางในแนวลึกกับกราฟทิศทางในรูปที่ 10.17 จะมีขั้นตอนเป็น ดังนี้

  32. 1.       เริ่มต้นวิ่งผ่านที่โหนด A1.       เริ่มต้นวิ่งผ่านที่โหนด A A 2.       ใช้รีเคอร์ซีฟวิ่งผ่านโหนด B และเก็บโหนดในสแตก {E,D} A, B 3.       ใช้รีเคอร์ซีฟวิ่งผ่านโหนด F และเก็บโหนด G ในสแตก {E,D,G} A, B,F 4.        ใช้รีเคอร์ซีฟวิ่งผ่านโหนด I A, B, F, I 5.        ใช้รีเคอร์ซีฟวิ่งผ่านโหนด H A, B, F, I, H 6.   ถอยกลับมาที่โหนด F ดึงโหนด G จากสแตก {E,D} และใช้รีเคอร์ซีฟวิ่งผ่านโหนด G A, B, F, I, H, G 7.  ใช้รีเคอร์ซีฟวิ่งผ่านโหนด C A, B, F, I, H, G, C 8.  ใช้รีเคอร์ซีฟวิ่งผ่านโหนด D A, B, F, I, H, G, C, D 9.   ถอยกลับไปเรื่อย ๆ มาที่โหนด A ดึงโหนด D  จากสแตกแต่วิ่งผ่านไปแล้วจึงดึงโหนด E จากสแตก {} และใช้รีเคอร์ซีฟวิ่งผ่านโหนด E                A, B, F, I, H, G, C, D, E

  33. การนำอัลกอริทึมแบบรีเคอร์ซีฟมาใช้มีการทำงานเป็นช่วง ๆ ตามที่เรียกตัวเองมาใช้ การทำงานจะสิ้นสุดลงที่โหนดแรกเมื่อตอนเริ่มต้นโดยไม่มีโหนดเหลือในสแตกก็จะได้โหนดที่ถูกวิ่งผ่านเรียงตามลำดับในแนวลึกก่อน คือ A, B, F, I, H, G, C, D, E ถ้าเริ่มต้นที่โหนด B จะมีโหนดที่ถูกวิ่งผ่านเรียงตามลำดับในแนวลึกก่อน คือ B, F, I, H, G, C, D ส่วนโหนด Aและ E ไม่สามารถวิ่งไปได้ เมื่อใช้อัลกอริทึมแบบรีเคอร์ซีฟจะมีการสร้างสแตกขึ้นมาทำงานให้อัตโนมัติ แต่ถ้าเปลี่ยนเป็นใช้การวนซ้ำแบบเดิมเช่นเดียวกับการวิ่งตามแนวกว้างต้องสร้างสแตกและจัดการเอง • อัลกอริทึมที่นำมาใช้ในการค้นหาตามแนวลึกมักถูกนำมาใช้งานบ่อยกับกราฟทิศทาง เช่น ต้องการทราบว่าแต่ละโหนดในกราฟสามารถวิ่งไปถึงโหนดอื่น ๆ ได้หรือไม่(Reachability)  จากที่ผ่านมาทราบว่าเมื่อเริ่มต้นที่โหนด B จะไม่สามารถวิ่งไปถึงโหนด A และ E ได้

  34. ตัวอย่างการใช้กราฟหาเส้นทางที่สั้นที่สุดตัวอย่างการใช้กราฟหาเส้นทางที่สั้นที่สุด ปัญหาซึ่งเป็นที่รู้จักคือการหาเส้นทางที่สั้นที่สุด (Routing Problem) เช่นการส่งข้อมูลในเครือข่ายให้เร็วที่สุด การเลือกเส้นทางการบินระหว่างเมืองการส่งสินค้าทางรถยนต์ที่ต้องรวดเร็วและประหยัดน้ำมัน การออกแบบอัลกอริทึมเพื่อค้นหาเส้นทางที่สั้นที่สุด (Shortest Path Algorithm) จะนำอัลกอริทึมการวิ่งตามเส้นทางในแนวกว้างมาปรับปรุงและใช้กับกราฟที่เอจมีน้ำหนักได้เป็นอัลกอริทึมดังในตารางที่ 10.3 ตารางที่ 10.3 อัลกอริทึมการหาเส้นทางที่สั้นที่สุดในกราฟ 1.วิ่งผ่านไปยังโหนด N ให้เป็นโหนดต้นทาง และทำเครื่องหมายวิ่งผ่านแล้ว2.กำหนดระยะทางให้เท่ากับ 03.สร้างคิวขึ้นมาและเก็บโหนด N4.ถ้ายังไม่วิ่งผ่านโหนดปลายทาง และคิวยังไม่ว่างให้ทำดังนี้            4.1ทำการลบโหนด N ออกจากคิว            4.2สำหรับทุก ๆโหนด  W ที่เชื่อมต่อกับโหนด ให้ทำดังนี้                        a.เก็บค่าระยะทางที่สั้นที่สุดของโหนด ห่างจากโหนดต้นทาง                        b.ถ้าโหนด W  ยังไม่ถูกวิ่งผ่าน                                       b.1วิ่งไปที่โหนด W ทำเครื่องหมายวิ่งผ่านแล้ว

  35. 5.ถ้าโหนดต้นทางไม่สามารถวิ่งไปถึงโหนดปลายทางแจ้งว่าโหนดต้นทางวิ่งไปไม่ถึงโหนดปลายทางไม่เช่นนั้นแสดงเส้นทางที่สั้นที่สุดจากโหนดต้นทางวิ่งไปยังโหนดปลายทาง5.ถ้าโหนดต้นทางไม่สามารถวิ่งไปถึงโหนดปลายทางแจ้งว่าโหนดต้นทางวิ่งไปไม่ถึงโหนดปลายทางไม่เช่นนั้นแสดงเส้นทางที่สั้นที่สุดจากโหนดต้นทางวิ่งไปยังโหนดปลายทาง • อัลกอริทึมที่มีประสิทธิภาพในการหาเส้นทางที่สั้นที่สุดในกราฟ เรียกว่า อัลกอริทึมของดิจสตรา (Dijkatra’s Algorithm) เป็นการหาเส้นทางที่สั้นที่สุดของโหนดหนึ่งไปยังโหนดอื่น ๆ โดยใช้น้ำหนักของเอจ เรียกว่า ระยะทางสั้นที่สุด (Shortest Distance) ในอัลกอริทึมมีการใช้อาร์เรย์ Distance เพื่อเก็บระยะทางของแต่ละโหนดที่ห่างจากโหนดเริ่มต้น กำหนดค่าสูงสุด(Infinity) ให้กับทุกสมาชิก ใช้อาร์เรย์ Path บอกให้ทราบว่าโหนดนี้มาจากเส้นทางของโหนดใดและอาร์เรย์ Visited บอกให้ทราบว่าโหนดนี้มีการวิ่งผ่านไปแล้ว ทั้งสามอาร์เรย์อาจนำมารวมเป็นอาร์เรย์ 2 มิติ การทำงานของอัลกอริทึมนี้เมื่อใช้กับกราฟทิศทางในรูปที่ 10.18 จะมีขั้นตอนดังนี้

  36. รูปที่ 10.18ตัวอย่างกราฟทิศทางกับการหาเส้นทางที่สั้นที่สุด                1.       วิ่งผ่านที่โหนด V เป็นโหนดเริ่มต้น กำหนดค่า distance[0] = 0, Path[0] = 0, visited[0] = 1  ได้เป็นรูปที่ 10.19 (a) และเก็บโหนด V ลงในคิวลำดับความสำคัญ(Priority Queue) = {V} เพื่อโหนดที่มีระยะทางสั้นที่สุดถูกใช้งานก่อน                2.       ดึงโหนด V ออกจากคิวหาโหนดที่เชื่อมติดกันคือโหนด V และ V จะได้ว่าระยะทางจาก V ถึง V คือ distance[0] + ระยะทางระหว่าง V กับ V = 0 + 2 = 2 ระยะทางจาก V ถึง V คือ distance[0] + ระยะทางระหว่าง V กับ V = 0 + 9 = 9 เมื่อเปรียบเทียบกับค่าเดิมพบว่าน้อยกว่าก็เก็บแทนในอาร์เรย์ distance[1] และ     distance[5] เป็นรูปที่ 10.19 (b) Path[1], Path[5] = 0, visited[1], visited[5] = 1 เก็บโหนด Vและ V ลงคิว = {V , V}

  37.                 3.       ดึงโหนด V ออกจากคิวหาโหนดที่เชื่อมติดกันคือโหนด V , V , V  จะได้ว่า ระยะทางจาก V ถึง V คือ distance[1] + ระยะทางระหว่าง V กับ V = 2 + 8 = 10 ระยะทางจาก V ถึง V คือ distance[1] + ระยะทางระหว่าง V กับ V = 2 + 15 = 17 ระยะทางจาก V ถึง V คือ distance[1] + ระยะทางระหว่าง V กับ V = 2 + 6 = 8 เมื่อเปรียบเทียบกับค่าเดิมพบว่าน้อยกว่าก็เก็บแทนในอาร์เรย์ distance[2], distance[3], distance[5] เป็นรูปที่ 10.19 (c) Path[2], Patch[3], Patch[5], = 1 visited[1], visited[3] = 1 และเก็บลงคิว = {

  38.                     4.       ดึงโหนด V ออกจากคิวหาโหนดที่เชื่อมติดกันคือโหนด  V จะได้ว่า ระยะทางจาก V ถึง V คือ distance[5] + ระยะทาง V กับ V = 8 + 3 = 11 เมื่อเปรียบเทียบกับค่าเดิมพบว่าน้อยกว่าก็เก็บแทนในอาร์เรย์ distance[4] เป็นรูปที่ 10.19 (d) Path[4] = 5 visited[4] = 1 และเก็บลงคิว = { V,V,V}                     5.       ดึงโหนด V  ออกจากคิวหาโหนดที่เชื่อมติดกันคือโหนด V จะได้ว่า ระยะทางจาก  V ถึง V คือ distance[2] + ระยะทางระหว่าง V กับ V = 10 + 1 = 11 ค่าที่ได้เมื่อเปรียบเทียบกับค่าเดิมพบว่าน้อยกว่าก็เก็บแทนในอาร์เรย์ distance[3] เป็นรูปที่ 10.19 (e) Path[3] = 2 และคิว = {V,V} เนื่องจาก V ถูกวิ่งผ่านไปแล้วจึงไม่เก็บลงในคิวอีก                     6.       ดึงโหนด V ออกจากคิวหาโหนดที่เชื่อมติดกันคือโหนด V , V จะได้ว่า ระยะทางจาก V ถึง V คือ distance[4] + ระยะทางระหว่าง V = 11 + 7 = 18 ระยะทางจาก Vถึง V คือ distance[4] + ระยะทางระหว่าง V กับ V = 11 + 3 = 14 ค่าที่ได้เมื่อเปรียบเทียบพบว่ามากกว่าค่าเดิมจึงไม่เก็บลงในอาร์เรย์เป็นรูปที่ 10.19 (f) และคิว = {V}                      7.       ดึงโหนด V ออกจากคิวหาโหนดแต่ไม่มีเชื่อมติดกับโหนดใด และคิวว่างจึงจบการทำงาน

  39. รูปที่ 10.19 การเก็บค่าต่าง ๆ ในกาวิ่งตามเส้นทางแต่ละช่วง จากตัวอย่างเป็นการหาเส้นทางที่สั้นที่สุดโดยการเริ่มที่โหนด V  ไปหาโหนดใด ๆ ในกราฟระยะทางทราบได้จากอาร์เรย์ distance ส่วนเส้นทางทราบได้จากอาร์เรย์ Path เช่น ต้องการทราบเส้นทางที่สั้นที่สุดระหว่างโหนด V กับ V พบว่าระยะทางที่สั้นที่สุด คือ 11 และมีเส้นทาง คือ V à V à V à V และเมื่อเขียนเป็นโปรแกรมจะได้ดังในตารางที่ 10.4 คือ

  40. จากตัวอย่างโปรแกรมจะใช้กราฟทิศทางในรูปที่ 10.18 สร้างเป็นแมตทริกติดกันชื่อadjMatrixเก็บค่าระยะทางโหนดที่เชื่อมติดกัน สร้างอาร์เรย์ distance, Path, visited ไว้เก็บค่าระยะทาง เส้นทางที่สั้นที่สุด และถูกวิ่งผ่านตามลำดับ เมื่อมีการวิ่งผ่านไปยังโหนดใดจะมีการเก็บระยะทางที่สั้นที่สุดโดยเปรียบเทียบค่าเดิมที่ได้จากเส้นทางอื่นก่อนพร้อมกับเปลี่ยนเส้นทางให้ถูกต้อง ดังนี้ •    If(distance[i]>(distance[node]+adjMatrix[node][i])){   distance[i]=distance[node]+adjMatrix[node][i];   path[i]=node; } • ในขั้นตอนท้ายเป็นการแสดงเส้นทางที่มีระยะทางที่สั้นที่สุดของแต่ละโหนดไปหาโหนดเริ่มต้น ในอัลกอริทึมนี้มีการใช้คิวลำดับความสำคัญที่ให้ค่าน้อยกว่าสำคัญกว่า จึงเขียนเป็นprioritQ.hดังในตารางที่ 10.5 และเรียกมาใช้งานดังนี้

More Related