מבני נתונים ואלגוריתמים - מחברת קורס/גרפים/אלגוריתם Union-Find
הגדרה: בהינתן גרף , רכיב הקשירות של הוא קבוצת כל הצמתים שאפשר להגיע אליהם מ. |
דף זו עוסק באלגוריתם לרכיבי קשירות בגרף לא מכוון.
כדאי לדעת: בספר הקורס, הפרק "Disjoint Sets" (תת-פרק 1) מכסה נושא זה. |
מימוש C++ |
הבעיה
עריכהנתון גרף לא מכוון . בהינתן שני צמתים כלשהם , רוצים לדעת האם ברכיב הקשירות של (כלומר, האם יש מסלול ביניהם).
דוגמה: באי באוקיינוס השקט יש שש ערים . בעבר היו כל שתי ערים מחוברות זו לזו בדרך ישירה מאחת לשניה. כעת, בעקבות שיטפון, אלה הדרכים היחידות שנותרו:
|
דוגמה: במבני נתונים לקבוצות זרות, ראינו את הבעיה הבאה. סטודנטים מתארגנים לקבוצות לימוד למבחן. נניח את ההנחה המקורבת שאם שני סטודנטים מחליטים ללמוד באותה קבוצה, אז הקבוצה שאליה שייך הסטודנט הראשון מתאחדת עם הקבוצה שאליה שייך הסטודנט השני. נרצה להיות מסוגלים, בהינתן שני סטודנטים, להחליט האם הם שייכים לאותה קבוצה או לא.נניח שיש שמונה סטודנטים: . נתן לחשוב עליהם בתחילה כ-8 קבוצות זרות, שכ"א מורכבת מאיבר יחיד:
לבסוף, לכן, קבלנו את הקבוצות הזרות : נרצה להיות מסוגלים, בהינתן ו לדוגמה, לענות האם הם שייכים לאותה קבוצה (במקרה זה - לא). כעת כשאנו מכירים גרפים מעט, נוכל לשים לב שאפשר להציג את הבעיה כאחת מתורת הגרפים. כל סטודנט מיוצג ע"י צומת, ואם שני סטודנטים מחליטים ללמוד ביחד, מייצגים זאת ע"י קשת ביניהם. השאלה האם ו לדוגמה, שייכים לאותה קבוצה, שקולה לשאלה האם הם שייכים לאותו רכיב קשירות. |
אלגוריתם Union-Find
עריכהלהלן הפסוודו-קוד לאלגוריתם Union-Find, המשתמש במבנה הנתונים לקבוצות זרות שראינו:
Connected-Components(G)
1 V = V(G)
2 Sets = Make-Array( Length(V) )
3 for v in V
4 Sets[v] = Make-Set()
5 for (u, v) in E(G)
6 if Find-Set(Sets[u]) != Find-Set(Sets[v])
7 Union(Sets[u], Sets[v])
8 return Sets
ולהלן דוגמה לשימוש בו:
1 Sets = Connected-Components(G)
# Prints True.
1 Print( Find-Set(Sets[1]) == Find-Set([3]) )
# Prints False.
2 Print( Find-Set(Sets[2]) == Find-Set([3]) )
הנה הסבר לUnion-Find
:
- ב2 מייצרים את המערך
Sets
, המכיל לכל צומת את הקבוצה שלו. - ב3-4 בונים לכל צומת קבוצה בגודל 1.
- ב5-6 עוברים על כל הקשתות, ומאחדים, לכל קשת, את צומת ההתחלה וצומת הסוף של הקשת אם יש צורך.
ניתוח סיבוכיות
עריכה3-4 מייצרות קבוצות זרות שונות, ולאחר מכן מבצעים בדיקות, ולכל היותר פעולות איחוד.
לכן, מבחינת מבנה הנתונים לקבוצות זרות, מדובר בסדרה של
פעולות, מתוכן פעולות מסוג Make-Set
. כפי שראינו בניתוח המימוש היעיל למבני נתונים לקבוצות זרות, הסיבוכיות היא , לכן.
כעת נותר לחשב את עלויות הלולאות עצמן. אם הגרף נתון ברשימת שכנויות, אז 3 אורכת , ו5 אורכת .
הסיבוכיות הכוללת, לכן, היא .
הקשר לאלגוריתם Grow-Tree
עריכהאפשר לחשוב על האלגוריתם שראינו זה עתה כמקרה פרטי של "אלגוריתם" Grow-Tree. כדי להדגיש זאת, הנה ווריאציה של האלגוריתם שמחזירה קבוצת קשתות עץ-פורש בהנתן גרף לא-מכוון קשיר.
Connected-Components(G)
1 V = V(G)
2 Sets = Make-Array( Length(V) )
3 E' = Make-List
4 for v in V
5 Sets[v] = Make-Set()
6 for (u, v) in E(G)
7 if Find-Set(Sets[u]) != Find-Set(Sets[v])
8 Union(Sets[u], Sets[v])
9 Insert(E', (u, v))
10 return E'
מהדימיון בין האלגוריתמים, קל לראות שכל מה שהוכחנו לגבי Grow-Tree תקף גם כאן: בהנתן גרף לא-מכוון וקשיר, ווריאציית האלגוריתם תבנה עץ פורש. בהרחבה פשוטה של ההוכחה, קל לראות שהאלגוריתם בונה יער במקרה הכללי של גרף לא-מכוון.
כדאי לדעת: בקורס נלמד מספר אלגוריתמים (ודמויי-אלגוריתמים) לבניית עץ פורש. הם מתוארים בתרשים הבא:
|
הפרק הקודם: עצים |
אלגוריתם Union-Find תרגילים |
הפרק הבא: אלגוריתמים למציאת עפ"מ |