Download presentation
Presentation is loading. Please wait.
1
מבני נתונים ויעילות אלגוריתמים
מכללת אורט כפר-סבא מבני נתונים ויעילות אלגוריתמים מבוא לתורת הגרפים אורי וולטמן
2
חידה לחימום אמיר ומיכל משחקים במשחק. על לוח המשחק מונחים 1,000 מטבעות בשורה. לכל מטבע בשורה יש ערך שהוא מספר חיובי והשחקנים יודעים בתחילת המשחק את ערכיהם של כל המטבעות. המשחק מתנהל בתורות, לסירוגין. בכל תור, השחקן שמשחק בוחר מטבע מאחד משני קצוות השורה ולוקח אותו לקופה שלו. לאחר 1,000 תורות נגמרים המטבעות בשורה. בשלב זה, סופרים את סכום ערכי המטבעות שבקופה של כל אחד מהשחקנים. השחקן שצבר סכום גדול יותר, מנצח במשחק. במקרה של שוויון בסכומים, המשחק מוכרז כתיקו. אמיר משחק ראשון. הוא ממש לא רוצה להפסיד. לא אכפת לו אם המשחק יסתיים בתיקו או בניצחון שלו. מצאו אסטרטגיה עבור אמיר שתבטיח שהוא לא יפסיד במשחק.
3
הגדרות יסודיות תורת הגרפים (Graph Theory) היא ענף חשוב במתמטיקה, ולו יישומים רבים בתחומי מדע שונים. גם במדעי המחשב משתמשים בגרפים, בתור טיפוס נתונים עליו ניתן להפעיל אלגוריתמים שימושיים. אבל מה זה בעצם 'גרף'? אנחנו נגדיר גרף (graph) בתור אוסף של צמתים או קודקודים (באנגלית vertices, וביחיד – vertex), אשר ביניהם יש קשתות או צלעות (באנגלית edges). נסמן את קבוצת הקודקודים באות V, ואת קבוצת הצלעות באות E. בדרך-כלל מכנים גרפים בשמות (כגון G), וכותבים זאת כך: G = (V,E). הנה, למשל, מספר גרפים:
4
דרגה של קודקוד זוג קודקודים הנמצאים משני צידיה של קשת נקראים סמוכים (adjacent) או שכנים. נעיין בגרף הבא, אשר קודקודיו מסומנים באותיות: בגרף זה, שכניו של הקודקוד x הם u ו-v. השכן היחידי של הקודקוד y הוא הקודקוד u. הקודקוד w הוא קודקוד מבודד, ללא שכנים. לקודקוד v יש קשת היוצאת ממנו ונכנסת אליו חזרה. קשת כזו מכונה לולאה עצמית (self loop), או בקיצור – לולאה (loop). הגדרה: נגדיר דרגה (degree) של קודקוד v בתור מספר הקשתות הנוגעות בו, ונסמן זאת d(v). למשל, עבור הגרף הזה מתקיים: d(x) = 2 d(u) = 3 d(y) = 1 d(w) = 0 d(v) = 4 ניתן לראות שדרגתו של קודקוד מבודד היא אפס (כי אין אף קשת שנוגעת בו). כמו כן, עבור הקודקוד v, רואים כי הלולאה "תורמת" 2 לדרגת הקודקוד (פעם כשהקשת יוצאת מהקודקוד, ופעם שהקשת נכנסת).
5
דרגה של קודקוד טענה: בכל גרף, סכום דרגות כל הקודקודים שווה לפעמיים מספר הקשתות: טענה זו מכונה לעיתים 'משפט לחיצת הידיים': נדמיין קבוצת אנשים שחלקם לוחצים ידיים האחד עם השני, ונייצג קבוצה זו על-ידי גרף. כל אדם ייוצג על-ידי קודקוד, ונמתח קשת בין שני קודקודים אם שני האנשים לחצו ידיים. נניח שכל אדם זוכר לכמה אנשים אחרים הוא לחץ ידיים (זוהי דרגת הקודקוד). משמעות המשפט היא שאם נבקש מכל אדם לומר את מספר האנשים איתם הוא לחץ ידיים, ונסכם את כל המספרים, נקבל מספר הגדול פי 2 ממספר לחיצות הידיים שהתבצעו.
6
דרגה של קודקוד טענה: בכל גרף, סכום דרגות כל הקודקודים שווה לפעמיים מספר הקשתות: האם קיים גרף בעל 7 קודקודים, שדרגתו של כל אחד מהם היא 5? האם קיים גרף שסדרת דרגותיו היא... 1, 2, 2, 3, 4, 5. 0, 0, 1, 1, 1, 1, 1, 2, 3. 0, 4, 4, 5, 5. 2, 2, 3, 3, 4, 5.
7
דרגה של קודקוד סדרת מספרים שלמים אי-שליליים עבורה קיים גרף שזוהי סדרת דרגות קודקודיו, נקראת סדרה גראפית (graphic sequence). כפי שראינו, לא כל סדרה היא גראפית, וקיימות סדרות של מספרים שאינן מייצגות דרגות קודקודים של גרף. קיימים אלגוריתמים (כגון אלגוריתם Havel-Hakimi) המקבלים סדרה גראפית, ובונים ממנה גרף. שאלה: הוכיחו כי אם בגרף יש n קודקודים ו- n+4 קשתות, וכל הדרגות הן לפחות 3, אזי n < 8 .
8
גרף פשוט ישנם גרפים אשר בהם יש יותר מקשת אחת בין שני קודקודים. קשתות כאלה נקראות קשתות מקבילות או קשתות מרובות (multiple edges). הגרף הבא הוא דוגמא לגרף אשר יש בו קשתות מקבילות: גרף שאיננו מכיל קשתות מקבילות וגם לא לולאות עצמיות, נקרא גרף פשוט (simple graph). רוב הגרפים בהם נעסוק יהיו פשוטים. כל הגרפים שראינו עד כה, למעט זה שקודקודיו סומנו באותיות, היו גרפים פשוטים. לפניכם שלושה גרפים. קבעו לגבי כל אחד האם הוא פשוט או לא:
9
גרף מכוון לעיתים, נרצה לתת לקשתות הגרף כיוון (למשל, אם אנחנו משתמשים בגרף על מנת לייצג רשת של כבישים, וחלק מהכבישים הם חד-סיטריים). לגרף שבו הקשתות הן מכוונות נקרא גרף מכוון (directed graph, או בקיצור digraph). גרף שבו הקשתות אינן מכוונות (וכל הגרפים בהם נתקלנו עד כה היו כאלו) נקרא גרף לא-מכוון (non-directed graph). דוגמא לגרף מכוון: אם ניקח גרף מכוון, ונתעלם מהכיוונים על הקשתות, נקבל גרף לא-מכוון הנקרא גרף התשתית שלו. בגרף מכוון, נגדיר לכל צומת את דרגת הכניסה (in-degree) ודרגת היציאה (out-degree) בתור מספר הקשתות המכוונות הנכנסות והיוצאות מתוך הצומת, בהתאמה. נסמן ב-din(x) את דרגת הכניסה של צומת x, ואת דרגת היציאה שלו - dout(x). ברור שדרגה של כל צומת (בגרף התשתית הלא-מכוון) שווה לסכום דרגת הכניסה ודרגת היציאה: din(x) + dout(x) = d(x). בגרף מכוון פשוט מותר שיהיו שתי קשתות המחברות בין שני קודקודים, בתנאי שכיווניהן הפוכים. קשתות כאלה נקראות קשתות אנטי-מקבילות. נסחו גירסה של משפט לחיצות הידיים עבור גרפים מכוונים.
10
גרף ממושקל לעיתים נרצה להצמיד לכל קשת מספר הנקרא המשקל (weight) של הקשת. המשקל של קשת יכול לייצג דברים שונים. אם, למשל, הגרף מייצג מערכת כבישים (כל קודקוד מייצג עיר, וכל קשת מייצגת כביש המחבר שני ערים), אז המשקל של קשת יכול לציין, לדוגמא: את המרחק בקילומטרים שבין עיר לעיר. את מהירות הנסיעה המקסימלית בקמ"ש בכביש הזה. את המחיר שצריך לשלם בשקלים עבור הנסיעה בכביש (אם מדובר בכביש אגרה), וכו'. גרף שבו לכל קשת מוצמד משקל, נקרא גרף ממושקל (weighted graph). כל הגרפים בהם נתקלנו עד כה היו גרפים לא-ממושקלים (un-weighted graphs). להלן דוגמא לשני גרפים ממושקלים, האחד מהם מכוון והשני לא-מכוון: משקל של קשת אינו בהכרח מספר טבעי. ייתכנו קשתות שמשקליהן הם שברים, מס' שליליים, אפס, וכו'.
11
שאלה עד כה הכרנו מספר תכונות לגבי גרפים. ראינו כי גרף יכול להיות...
פשוט / לא פשוט מכוון / לא מכוון ממושקל / לא ממושקל שרטטו דוגמא לגרף אחד מכל אחד מהצירופים האפשריים של שלושת התכונות (לדוגמא: גרף פשוט לא-מכוון וממושקל, גרף לא-פשוט לא-מכוון ולא-ממושקל, וכו'). כמה צירופים כאלו יש?
12
שאלה משפחה מפורסמת של גרפים נקראת הגרפים השלמים (complete graphs), והיא מסומנת Kn. הגרף השלם על n קודקודים, עבור n שלם וחיובי (טבעי), הוא גרף פשוט שבו כל שני קודקודים הם סמוכים. לדוגמא, הגרפים K2, K3, K4 יראו כך: שרטטו את K5 ואת K6. איך יראה K1 ? ספרו את מספר הקשתות עבור כל אחד מהגרפים Ki , עבור i = 1..6. האם תוכלו לתת נוסחא כללית עבור מספר הקשתות של הגרף Kn ולהסביר מדוע היא נכונה? נסו להוכיח את טענתכם בשתי דרכים: ע"י בניית נוסחת נסיגה ופתירתה, וע"י שימוש במשפט לחיצת הידיים.
13
מסלולים נכנה בשם מסלול (path) כל סדרה של קשתות המחברות קודקודים סמוכים. אורך של מסלול פירושו מספר הקשתות שבו. לדוגמא: AEBD הוא מסלול באורך 3. CAB מסלול באורך 2. מסלול שבו הקודקוד הראשון והאחרון הם אותו הקודקוד, נקרא מעגל (cycle). לדוגמא: AEBA הוא מעגל באורך 3. מסלול יקרא פשוט (simple path) אם אף קודקוד לא חוזר בו יותר מפעם אחת, ומעגל יקרא פשוט (simple cycle) אם אף קודקוד, פרט לקודקוד הראשון (שהוא גם האחרון), לא חוזר בו יותר מפעם אחת, ואף קשת לא חוזרת יותר מפעם אחת. בכל הדוגמאות שראינו לעיל הופיעו מסלולים פשוטים ומעגלים פשוטים. המסלול AEBDBE הוא מסלול לא פשוט באורך 5. המעגל BACAB הוא מעגל לא פשוט באורך 4. האם בהגדרה ניתן לוותר על החלק "ואף קשת..."? גרף לא-מכוון ייקרא קשיר (connected) אם מכל קודקוד ניתן להגיע לכל קודקוד אחר על-ידי מסלול.
14
גרף קשיר כאמור, גרף לא-מכוון ייקרא קשיר (connected) אם מכל קודקוד ניתן להגיע לכל קודקוד אחר על-ידי מסלול. נביט בגרף הלא-קשיר הבא: בגרף לא-מכוון, רכיב קשירות (connected component) הוא תת-גרף קשיר של הגרף המקורי הכולל את כל הקודקודים שניתן להגיע אליהם מקודקוד נתון. לדוגמא, בגרף הנתון ישנם שלושה רכיבי קשירות: רכיב קשירות אחד כולל את הקודקודים 1,2,3,4,8. רכיב קשירות אחר כולל את הקודקודים 0,5,6. רכיב קשירות נוסף כולל את הקודקוד 7. קודקוד כזה, שדרגתו היא אפס, נקרא קודקוד מבודד (isolated vertex). קודקוד מבודד הוא קודקוד הנמצא לבדו ברכיב קשירות. בגרף קשיר יש בדיוק רכיב קשירות אחד.
15
גרף קשיר בחוזקה גרף מכוון ייקרא קשיר היטב או קשיר בחוזקה (strongly connected) אם מכל קודקוד ניתן להגיע לכל קודקוד אחר על-ידי מסלול מכוון. לדוגמא, הגרף G1 הוא קשיר בחוזקה, ואילו הגרף G2 אינו קשיר בחוזקה: בגרף מכוון, רכיב קשירות בחוזקה (strongly connected component), המכונה בקיצור רק"ח (SCC), הוא תת-גרף קשיר-בחוזקה של הגרף המקורי הכולל את כל הקודקודים שניתן להגיע אליהם מקודקוד נתון. בגרף קשיר בחוזקה יש בדיוק רכיב קשירות בחוזקה (רק"ח) אחד. G1 G2
16
מטריצת סמיכויות אחת הדרכים הנפוצות לייצג גרף בזיכרון המחשב, היא באמצעות מטריצת סמיכויות (adjacency matrix), הנקראת גם מטריצת שכנויות. שיטה זו היא אפקטיבית בעיקר כאשר ידוע מראש המס' המקסימלי של קודקודים בגרף. נסמן מס' זה ב-n, ונניח שלכל קודקוד יוצמד מספר בין 0 לבין n-1. כעת, נגדיר מטריצה ריבועית A בגודל nxn. אם קיימת קשת בין קודקוד i לבין קודקוד j, אז נציב את הערך 1 (או את הערך הבוליאני TRUE) בתא A[i][j]. אם לא קיימת קשת כזו, אז נציב בתא זה את הערך 0 (או את הערך הבוליאני FALSE). לדוגמא: נשים לב שמטריצת הסמיכויות היא מטריצה סימטרית. מדוע זה כך?
17
מטריצת סמיכויות כיצד ניתן לחשב, באמצעות מטריצת סמיכויות, את הדרגה (degree) של קודקוד? באמצעות ספירת מספר ה-1-ים בשורה המתאימה לו, או בעמודה המתאימה לו. מהי סיבוכיות זמן הריצה של חישוב זה? Ө(n) כיצד ניתן לגלות, באמצעות מטריצת סמיכויות, האם יש בגרף לולאה עצמית? נבדוק האם המספר 1 מופיע על האלכסון הראשי של המטריצה. שימו לב שבמקרה כזה, כדי לחשב את דרגת הקודקוד יש לספור את האלכסון הראשי פעמיים. כיצד ניתן לזהות, באמצעות מטריצת סמיכויות, קודקוד מבודד? בשורה/בעמודה המתאימה לקודקוד, מופיעים רק אפסים (פרט לאלכסון הראשי). כיצד תיראה מטריצת הסמיכויות של גרף שלם Kn? כל הערכים במטריצה יהיו 1-ים, פרט לאלכסון הראשי שיכיל רק 0-ים. מה תהיה סיבוכיות זמן הריצה של אלגוריתם, הבודק האם הגרף אוילריאני? Ө(n2)
18
מטריצת סמיכויות ראינו כיצד ניתן לייצג באמצעות מטריצת סמיכויות גרף בלתי מכוון. אולם האם תעבוד שיטה זו גם עבור גרף מכוון? נשים 1 בתא A[i][j] אם יש קשת מכוונת היוצאת מ-i ונכנסת ל-j. בשיטה זו, מטריצת הסמיכויות לא תהיה בהכרח סימטרית, משום שמקיומה של קשת מכוונת מקודקוד i לקודקוד j לא ניתן להסיק שקיימת קשת מכוונת מקודקוד j לקודקוד i. מה מאפיין גרף מכוון שמטריצת הסמיכויות שלו היא סימטרית? בצד כל קשת מכוונת המופיעה בו, מופיעה גם קשת אנטי-מקבילה. כיצד ניתן לחשב את דרגת היציאה (out-degree) של קודקוד? לספור את כמות ה-1-ים בשורה המתאימה לקודקוד. כיצד ניתן לחשב את דרגת הכניסה (in-degree) של קודקוד? לספור את כמות ה-1-ים בעמודה המתאימה לקודקוד.
19
מטריצת סמיכויות נניח שרוצים לייצג באמצעות מטריצת סמיכויות גרף ממושקל (weighted), מכוון או בלתי מכוון. הנה הצעה: אם לא קיימת קשת בין קודקוד i לבין קודקוד j אז נשים 0 בתא A[i][j], ואם קיימת קשת בין שני הקודקודים – אז בתא A[i][j] נאחסן מספר המציין את משקל הקשת. איזו חולשה יש בפתרון הזה? הפתרון הזה יעבוד, רק בתנאי שאסור שמשקל קשת יהיה שווה לאפס! אם מרשים שמשקל של קשת יהיה שווה לאפס, לא נדע להבחין בין מקרה בו בין שני קודקודים לא קיימת קשת כלל, לבין מקרה בו קיימת קשת, אולם המשקל שלה הוא אפס. אפשרות אחרת, היא להגדיר מטריצת סמיכויות שכל אחד מהתאים בה מכיל שני ערכים: דגל בוליאני הקובע האם קיימת קשת או לא, ומספר המציין את משקל הקשת (אם קיימת). לדוגמא: struct edge { int exists; /* שדה שערכו 1 אם קיימת קשת, ו-0 אם לא */ float weight; /* שדה שערכו משקל הקשת, אם היא קיימת */ }; struct edge adjacency_matrix[N][N];
20
מטריצת סמיכויות לדוגמא, את הגרף המכוון והממושקל הזה:
נייצג באמצעות מטריצת הסמיכויות הבאה: מה סיבוכיות זמן הריצה של אלגוריתם המוצא את משקל הקשת הקלה ביותר? Ө(n2) שיטת ייצוג זו אינה תומכת בגרפים עם קשתות מקבילות (יותר מקשת אחת בין שני קודקודים). כיצד ניתן לייצג גרף כזה? ניתן לשים בכל תא במטריצה מצביע לראש רשימה מקושרת של מבנים, כאשר כל מבנה מייצג קשת ומכיל שדה ובו משקל הקשת.
21
רשימת סמיכויות שיטה נוספת לייצג גרף בזיכרון המחשב, היא באמצעות רשימת סמיכויות (adjacency list), הנקראת גם רשימת שכנויות. הרעיון הוא להגדיר מערך (או רשימה מקושרת) שכל אחד מאיבריו ייצג קודקוד אחד, ולכל אחד מאיברים אלה – תוצמד רשימה מקושרת של כל הצמתים שהם שכנים של אותו הקודקוד. לדוגמא, הגרף המכוון הזה, ייוצג כך:
22
רשימת סמיכויות כיצד ניתן לייצג גרפים ממושקלים בשיטה זו?
נוסיף לכל חוליה ברשימה המקושרת שדה נוסף, המייצג את משקל הקשת. לדוגמא: אם ידוע שהגרף הוא דליל (sparse), כלומר – שמספר הקשתות בו קטן מאוד ביחס למספר הקשתות האפשריות, באיזה ייצוג עדיף להשתמש: במטריצת סמיכויות או ברשימת סמיכויות? האם ניתן לייצג באמצעות רשימת סמיכויות גם גרף בלתי מכוון?
23
תרגיל נתון גרף G = (V,E), שהוא פשוט, בלתי מכוון ובלתי ממושקל:
חשבו את סכום האורכים של כל רשימות הסמיכויות. מה הקשר בין התוצאה שקיבלתם לבין מספר הקשתות בגרף?
24
תרגיל נתון גרף G = (V,E), שהוא פשוט, מכוון וממושקל:
25
תרגיל נתון גרף מכוון G = (V,E). נגדיר את הגרף המשוחלף GT = (V,ET) באופן הבא: קבוצת קודקודיו של הגרף המשוחלף היא V, כלומר – זהה לקבוצת הקודקודים של הגרף המקורי. קבוצת קשתותיו של הגרף המשוחלף היא ET, המוגדרת באופן הבא: כלומר, קשת (u,v) שייכת לקבוצת הקשתות ET של הגרף המשוחלף, רק אם הקשת (v,u) שייכת לקבוצת הקשתות E של הגרף המקורי. למשל, עבור הגרף G הבא: הגרף המשוחלף GT הוא: פתחו אלגוריתם המקבל כקלט את G, ומחשב את GT. כתבו את האלגוריתם בשתי גירסאות: במקרה שהגרף מיוצג כמטריצת סמיכויות ובמקרה שהגרף מיוצג כרשימת סמיכויות. נתחו את סיבוכיות זמן הריצה של שני האלגוריתמים.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.