מבני נתונים ואלגוריתמים - מחברת קורס/גרפים/חיפוש רוחבי
מתוך ויקיספר, אוסף ספרי הלימוד והמדריכים החופשי.
דף זו עוסק באלגוריתם למציאת המסלול הקצר ביותר בגרף מכוון מצומת מוצא כלשהו.
|
כדאי לדעת: בספר הקורס, הפרק "Elementary Graph Algorithms" (תת פרק 2) מכסה נושא זה, אולם אנו נשתמש בגרסה מעט פשוטה יותר מזו המופיעה בספר. |
|
מימוש C++ |
תוכן עניינים |
[עריכה] הבעיה
נתונים גרף מכוון
וצומת מוצא
כלשהו. בהינתן צומת
כלשהו, רוצים לדעת מהו המסלול הקצר ביותר מ
ל
.
|
דוגמה: בגרף הבא, נניח צומת מוצא
|
[עריכה] חיפוש רחבי
[עריכה] הרעיון הכללי
במהלך מציאת הפתרון נחזיק שני מבני נתונים:
Min-Dists, מערך שיחזיק את המרחקים הקצרים ביותר.q, תור שיחזיק את קבוצת הצמתים שאת מרחקיהם אנו קובעים כעת.
נפעל עפ"י הצעדים הבאים:
- בתחילה נאתחל את כל איברי
Min-Distsל∞, למעטMin-Dists[s], שאותו נאתחל ל0; נכניס אתsלq. - כל עוד
qאינו ריק, נשלוף ממנו צומת, נעדכן את ערכיMin-Distsשל שכניו, ונכניס אותם לתור עפ"י הצורך.
|
דוגמה: עבור הגרף שראינו לעיל, וצומת המוצא
כעת 2 בראש התור. נשלוף אותו ונעדכן את שכניו. כעת 6 בראש התור. נשלוף אותו ונעדכן את שכניו. כעת 3 בראש התור. נשלוף אותו ונעדכן את שכניו. כעת 7 בראש התור. נשלוף אותו ונעדכן את שכניו.
ממשיכים כך הלאה עד שהתור מתרוקן. |
[עריכה] פסוודו-קוד
להלן הפסוודו-קוד לחיפוש רחבי:
BFS(G, s) 1 q = Make-Queue() 2 Min-Dists = Make-Array( Length(V(G)) ) 3 for u in V(G) 4 Min-Dists[u] = u == s? 0 : ∞ 5 Enqueue(q, s) 6 while Size(q) > 0 7 u = Dequeue(q) 8 for v in A(g, u) 9 if Min-Dists[v] > Min-Dists[u] + 1 10 Min-Dists[v] = Min-Dists[u] + 1 11 Enqueue(q, v) 12 return Min-Dists
ולהלן דוגמה לשימוש בו:
1 Min-Dists = BFS(G, 1) # Prints 0. 2 Print( Min-Dists[1] ) # Prints 2. 3 Print( Min-Dists[3] ) # Prints 3. 4 Print( Min-Dists[4] )
הנה הסבר לBFS:
- ב1 מייצרים את את התור
q, וב2 מייצרים את את המערךMin-Dists. - הלולאה 6-11 פועלת כל עוד
qאינו ריק. - 7 מוציאה את האיבר הקדום ביותר שהוכנס ל ב
q, ו8-11 מעדכנת את שכניו.
[עריכה] נכונות
|
משפט: ב11, |
[עריכה] שלבי התור
ראשית נוכיח את המשפט הבא, המתאר את מצב ההתור q במהלך הלולאה 6-11.
|
משפט: התור
עבור |
מה בעצם טוען המשפט?בלולאה 6-11, q מכיל תמיד 0 או יותר צמתים שרשום להם מרחק כלשהו, שלאחריהם 0 או יותר צמתים שרשום להם מרחק גדול ב1. לעולם לא נראה בו זמנית בq צמתים שלהם שלושה ערכים שונים בMin-Dists.
|
דוגמה:
|
|
הגדרה: נאמר ש |
|
דוגמה: בפעם הראשונה שמגיעים לשורה 6, הכיל |
[עריכה] הוכחת הנכונות בעזרת שלבי התור
בעזרת אפיון תוכן התור בשלבים, נוכל להוכיח את המשפט הבא.
|
משפט: כאשר |
ראשית נשים לב שהמשפט למעשה אומר שני דברים:
- כאשר
qמגיע לשלב
, אז מרחקו הקצר ביותר של כל צומת בqהוא
. - אם מרחקו הקצר ביותר של צומת ב
qהוא
, אז הצומת יהיה בqכאשרqמגיע לשלב
.
להלן הוכחת המשפט.
הוכחה: ההוכחה היא באינדוקציה על
.
(בסיס האינדוקציה) q נמצא בשלב 0 כאשר
מוכנס אליו. קל לראות שהטענה מתקיימת: אכן מרחקו הקצר ביותר מ
ל
הוא 0, ואין צומת אחר שמרחקו מ
הוא 0.
(מעבר האינדוקציה) נניח שהטענה נכונה עד לשלב ה
(כולל), ונראה שהיא נכונה לשלב ה
.
נתבונן בצומת
שנמצא בתור בשלב
. נניח שמרחקו הקצר ביותר מ
גדול ממש מ
. מתי הוכנס
לתור? מתישהו בין שלב
לשלב
, כאשר מצאנו שהוא שכן של צומת
משלב
. אבל, לפי הנחת האינדוקציה, זה יש מסלול מ
ל
באורך
, ולכן יש מסלול מ
ל
באורך
. כלומר, אם
בתור בשלב
, אז מרחקו לכל היותר
.
כעת ניקח צומת
כלשהו (לא הצומת הקודם), שמרחקו מ
הוא
. אם זה המצב, אז קיים
כלשהו כך שקיים מסלול מ
ל
כלשהו באורך
, וכן יש קשת מ
ל
. (למעשה, ייתכן יותר מצומת יחיד כזה. נקרא בשם
לצומת הראשון המקיים זאת.) לפי הנחת האינדוקציה,
היה בתור בשורה 6 בשלב
. אבל מ8-11, ברור שהצומת
מוכנס לתור במהלך שלב זה.
[עריכה] ניתוח סיבוכיות
נניח שהגרף נתון ברשימת שכנויות.
1-2 פועלות בבירור בזמן
.
3-5 מבצעות
פעולות Enqueue, ולכן אורכות זמן
במקרה הגרוע.
כפי שראינו, כל צומת נכנס לכל היותר פעם אחת לq, ולכן 6-11 רצה לכל היותר
פעמים. 7 היא
, ולכן תורמת סה"כ
. 8-11 רצות
פעמים לכל צומת u, ולכן רצות סה"כ
פעמים לכל היותר. 9-11 הן
, ולכן תורמות סה"כ
.
הסיבוכיות, לכן, היא
במקרה הגרוע.
| הפרק הקודם: אלגוריתם Prim |
חיפוש רוחבי תרגילים |
הפרק הבא: אלגוריתם Dijkstra |
.
, לדוגמה, הוא
, וארכו 3.





, עבור
כלשהם, כך ש:



