כלליים שיטות חיפוש בבגרפים שיטה 1: חיפוש לרוחב S (readth irst Search) זמן: ) Θ( V + הרעיון: שימוש בתור.O שיטה 2: חיפוש לעומק S (epth irst Search) Θ( V + ) יהי =(V,) גרף כלשהו, V הוא צומת התחלת החיפוש. זמן: חיפוש לעומק הוא למעשה ביקור ראשון (preorder) אם הגרף הוא עץ בינרי. הרעיון: שימוש במחסנית,LO אלגוריתם רקורסיבי. Q תור, head(q) ראש התור. S מחסנית, top(s) ראש המחסנית. בשני האלגוריתמים נוספת לולאה חיצונית שקוראת להתחלת חיפוש מצומת or each nmarked S() / S() שעדיין לא ביקרנו בו: V do 1 2 S() 1. Visit & mark 2. Q insert() 3. While Q do אלגוריתם :S 3.1 or all nmarked w adj to head(q) do 3.1.1 Visit & mark w 3.1.2 Q insert(w) 3.2 Pop(Q) :S() שתי מטרות עיקריות: סריקה שיטתית של הגרף. מציאת מסלולים קצרים..1.2 3 4
הדגמת פעולת התור: :S() 5 6 7 :S() S() 1.Visit & mark 2. S psh() 3. While S do 8 אלגוריתם :S 3.1 or all nmarked w adj to top(s) do 3.1.1 Visit & mark w 3.1.2 S psh(w) 3.2 Pop(S) S() 1. Visit & mark אלגוריתם רקורסיבי: 2. or all nmarked w dj[] do S(w)
עצים ביער ה S ) (שני :S() הדגמת פעולת המחסנית: 9 10 אחד ביער ה S ) (עץ :S() :S() 11 12
סיווג הקשתות בגרף ע"י S גרף לא מכוון: יער ה( S( : קשת בעץ קשת T אם היא קשת מקודקוד (,) סיימנו את החיפוש ממנו במחסנית), לקודקוד היא קשת בעץ שמסומן ועדיין לא (כלומר נמצא שמגלים אותו בפעם הראשונה (עדיין לא היה במחסנית). קשת אחורה קשת (,) היא קשת אחורה אם היא קשת מקודקוד לאב קדמון שלו בעץ ה S (כלומר מקודקוד מסומן שעדיין לא סיימנו איתו לקודקוד מסומן שעדיין לא סיימנו איתו). למה: בביצוע S על גרף לא מכוון, כל קשת של אחורה. היא או קשת בעץ או קשת 13 14 הוכחה: תהי (,) קשת כלשהי של הגרף. נניח בה"כ שבביצוע ב לפני שביקרנו ב. על S לפני שסיימנו עם כי. dj[] קודם ביקרנו לכן סימנו קודם עם גרף מכוון: יער ה S : כעת אם ביקרנו בקשת,(,) לראשונה, בכיוון מ ל אזי (,) היא קשת בעץ edge.tree ואם ביקרנו בקשת,(,) לראשונה, בכיוון מ ל אזי (,) ה אי קשת אחורה edge,ack מכיוון שעדיין לא סיימנו עם שדרכו הגענו בפעם הראשונה ל.(,) 15 16
ז( קשת קדימה 17 קשת (,) קדימה אם היא קשת מאב קדמון בעץ ה S. לצאצא שלו S היא קשת בעץ ה קשת לרוחב (הצידה) קשת בין שני תתי עצים או בין שני עצים שונים ביער ה S. המאפיין קשתות (,) אלו הוא שהן קשתות מקודקוד מסומן החיפוש ממנו למחסנית). ההבדל הוא שקשת לקודקוד שכבר הסתיים (ולכן הוא כבר מסומן ומחוץ (,) היא קשת קדימה אם חיפוש ה S גילה קודם את קודקוד לפני הגילוי של קודוקד. לעומת זאת שקשת אם בחיפוש ה S ובהמשך ה S גילינו את. (,) היא קשת לרוחב קודם גילינו את 18 לסיכום סוגי קשתות ביער ה S : גרף לא מכוון: כל קשת שמופיעה בגרף או:.1.2 גרף מכוון: תופיע בתור קשת בעץ. היא פונה אחורה בעץ. כל קשת שמופיעה בגרף או:.1.2.3.4 תופיע בתור קשת בעץ. קשת קדימה. קשת אחורה. קשת לרוחב (הצידה). היתרון בזיהוי הקשתות: אפשר לבדוק האם הגרף מכיל מעגל. מסקנה: גרף לא מכוון הוא cyclic ללא מעגלים "א יער) S כלשהו שלו. הוכחה: ( ) אם ורק אם אין ברור שקשת אחורה קשתות אחורה ב ( ) מעגל. כיוון שאם אין קשתות אחורה אזי כל הקשתות הן Tree dge ע"פ הלמה הקודמת. כיצד נמצא מעגל בגרף כלשהו? האם קשת קדימה יוצרת בעיה? האם תמיד יש מעגל כשיש קשת אחורה? משפט: קיים בגרף מעגל אם"ם לכל S של יש קשת אחורה (לכל סדר מתחילים את הסריקה) הוכחה: פרושו לא משנה באיזה ולכן הגרף הוא יער ללא מעגלים. ( ) אחורה: מיידי, המעגל קיים (,) נניח קשת 19 20
( ) יהי ה נניח שקיים מעגל 0.0 1,..., k,, j S k) j 0 ( הקודקוד הראשון שחיפוש מגיע אליו. היות וזה מעגל אז יש j לכל אחד מהקדקודים במעגל, מסלול מ ולכן במהלך S( j ) נגיע לכל הקודקודים במעגל. לכן לפני שנצא מ( S( j אחד מ. i j, i בתת העץ של j, j+ הקשת ) שאלה: j כלומר, ולכן הקשת ניגע בכל כל אחד מהם ( j 1, j ) ( 1 אלגוריתם לזיהוי מעגל בגרף: נוסיף דגל פעילות לכל קודקוד שפירושו: היא קשת אחורה, מש"ל. או כיצד ניתן לזהות שמדובר בקשת אחורה ולא בקשת הצידה? olor[]=white עדיין לא טופל, עדיין לא התבצעה הקריאה.S() olor[]=ray כלומר סומן ועדיין החיפוש לא הסתיים ממנו (כלומר עדיין ברקורסיה). olor[]=lack ב הסתיים החיפוש שהחל S() ( יצא מהמחסנית). בשלב הראשון יש אתחול של כל הקדקודים כלא פעילים, כלומר כולם.White בשלב השני ישנה הלולאה החיצונית: or each nmarked S() V do 21 22 האלגוריתם: S() 1. olor[] = ray 2. or each w dj[] do 2.1. if olor[w] = White then 2.1.1. S(w) 2.2. else if olor[w] = ray קיים מעגל בגרף.2.2.1 then print זמן הריצה: 3. olor[] = lack O ( V + ) תרגיל: הנ"ל כך? O(V ) ההבחנה: כיצד אפשר לשפר את האלגוריתם שבגרף לא מכוון בגרף מכוון זמן הריצה יהיה יש לבדוק את כל הקשתות במקרה הגרוע כיוון שבגרף מכוון V קשתות לא יוצרות בהכרח מעגל! ואילו בגרף לא מכוון כדי שיווצר מעגל יש לבדוק לכל היותר V קשתות! ולכן ניתן לסיים את האלגוריתם לאחר שעברנו על V קשתות לכל היותר (או שיש פחות קשתות וגילינו מעגל, או שאין מעגל כלל). 23 24
אלגוריתם לסיווג הקשתות בגרף: נוסיף לכל קודקוד משתנה המציין את הגילוי זמן של הקודקוד בפעם V (discoery time) הראשונה במהלך ה S : הוא מספר בין 1 ל שמציין את d[] סדר הביקור בקדקודים במהלך הסריקה. 1 2 4 האלגוריתם: יש לבצע (,) על הגרף ועל כל קשת S שעוברים במהלך החיפוש יש לבדוק את דגל d הפעילות (color) הקדקודים ו בהתאם: ואת זמן הגילוי של קשת (,) בעץ T אם אפור ו לבן. קשת (,) אפור. אחורה אם אפור ו קשת (,) קדימה אם אפור ו שחור וגם.d[]<d[] קשת (,) לרוחב אם אפור ו שחור וגם.d[]>d[] 3 5 25 26 1. or each V do olor[]! White 2. time! 1 or each V do if olor[] = White then S() 27 אתחול: זמן: O(V) לולאה חיצונית: אלגוריתם הסיווג: במבנה ה S הדרושות. זמן הריצה הכללי: הרגיל עם התוספות O ( V + ) S() 1. olor[] = ray 2. d[]! time 3. time! time + 1 4. or each dj[] do 4.1. if olor[] = White then (,) קשת בע!.4.1.1 4.1.2. S() 4.2. else if olor[] = ray then (,) קשת אחורה.4.2.1 4.3. else if olor[] = lack then 4.3.1. if d[]<d[] then (,) קשת קדימה.4.3.1.1 4.3.2. else קשת לרוחב (,) 5. olor[] = lack 28
תרגיל: אוילר. נתון גרף (לא מכוון) שקיים בו מעגל יש לכתוב אלגוריתם המוצא (=המדפיס) את המעגל. פתרון: האלגוריתם מבוסס על :S נתחיל מעגל. S מקודקוד כלשהו עד שייסגר """" כיוון שלא עברנו על כל הקשתות אנו חוזרים אחורה ברשימה לקודקוד שממנו יוצאות קשתות שעדיין לא עברנו עליהן ומנסים ממנו ליצור מעגל נוסף שיכנס לתוך הרשימה הנוצרת. ב נחזור צעד אחד אחורה לקודקוד : וכך הלאה: """" סגרנו מעגל, ולכן נחזור אחורה ברשימה לקודקוד ממנו יש קשתות שעדיין לא ביקרנו בהן. 29 30 """"""" """"""" המעגל: """"""""" """" 31 32
האלגוריתם: S_eler() 1. for each nmarked edge (, ) 1.1. do mark edge (, ) 1.2. S_eler() 2. insert in front of a linked list end S_eler 3. print the linked list זמן: ) Θ( V + 33