מבני נתונים ואלגוריתמים - מחברת קורס/גרפים/אלגוריתם Union-Find


הגדרה:

בהינתן גרף , רכיב הקשירות של הוא קבוצת כל הצמתים שאפשר להגיע אליהם מ.


דף זו עוסק באלגוריתם לרכיבי קשירות בגרף לא מכוון.


כדאי לדעת:

בספר הקורס, הפרק "Disjoint Sets" (תת-פרק 1) מכסה נושא זה.



מימוש C++

boost::connected_components


הבעיה

עריכה

נתון גרף לא מכוון  . בהינתן שני צמתים כלשהם  , רוצים לדעת האם   ברכיב הקשירות של   (כלומר, האם יש מסלול ביניהם).




דוגמה:

באי באוקיינוס השקט יש שש ערים  . בעבר היו כל שתי ערים מחוברות זו לזו בדרך ישירה מאחת לשניה. כעת, בעקבות שיטפון, אלה הדרכים היחידות שנותרו:


 
הקשר בין הערים לאחר השיטפון.


נרצה להיות מסוגלים, בהינתן   ו  לדוגמה, לענות האם הם עדיין נתן להגיע מהאחד לשני (במקרה זה - לא).




דוגמה:

במבני נתונים לקבוצות זרות, ראינו את הבעיה הבאה.

סטודנטים מתארגנים לקבוצות לימוד למבחן. נניח את ההנחה המקורבת שאם שני סטודנטים מחליטים ללמוד באותה קבוצה, אז הקבוצה שאליה שייך הסטודנט הראשון מתאחדת עם הקבוצה שאליה שייך הסטודנט השני. נרצה להיות מסוגלים, בהינתן שני סטודנטים, להחליט האם הם שייכים לאותה קבוצה או לא.נניח שיש שמונה סטודנטים:  . נתן לחשוב עליהם בתחילה כ-8 קבוצות זרות, שכ"א מורכבת מאיבר יחיד:


  1.  ו  מחליטים ללמוד ביחד.
  2.  ו  מחליטים ללמוד ביחד.
  3.  ו  מחליטים ללמוד ביחד.
  4.  ו  מחליטים ללמוד ביחד.
  5.  ו  מחליטים ללמוד ביחד.

לבסוף, לכן, קבלנו את הקבוצות הזרות  :

נרצה להיות מסוגלים, בהינתן  ו   לדוגמה, לענות האם הם שייכים לאותה קבוצה (במקרה זה - לא).

כעת כשאנו מכירים גרפים מעט, נוכל לשים לב שאפשר להציג את הבעיה כאחת מתורת הגרפים. כל סטודנט מיוצג ע"י צומת, ואם שני סטודנטים מחליטים ללמוד ביחד, מייצגים זאת ע"י קשת ביניהם.

 
הקשרים בין הסטודנטים.

השאלה האם  ו   לדוגמה, שייכים לאותה קבוצה, שקולה לשאלה האם הם שייכים לאותו רכיב קשירות.


אלגוריתם 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 תקף גם כאן: בהנתן גרף לא-מכוון וקשיר, ווריאציית האלגוריתם תבנה עץ פורש. בהרחבה פשוטה של ההוכחה, קל לראות שהאלגוריתם בונה יער במקרה הכללי של גרף לא-מכוון.


 

כדאי לדעת:

בקורס נלמד מספר אלגוריתמים (ודמויי-אלגוריתמים) לבניית עץ פורש. הם מתוארים בתרשים הבא:
 
היררכיית האלגוריתמים לבניית עץ פורש.
  1. "אלגוריתם" Grow-Tree בונה עץ פורש מגרף לא-מכוון קשיר. קל לשנותו כך שיבנה יער קטן ככל האפשר מגרף לא-מכוון.
  2. אלגוריתם Union-Find מוצא את רכיבי הקשירות של גרף לא מכוון. קל לשנותו כך שיבנה עץ פורש מגרף לא מכוון קשיר.
  3. "אלגוריתם" Grow-MST בונה עץ פורש מינימום מגרף לא-מכוון קשיר בעל טבלת עלויות לקשתות. הוא מקרה פרטי של Grow-Tree.
  4. אלגוריתם Kruskal בונה עץ פורש מינימום מגרף לא-מכוון קשיר בעל טבלת עלויות לקשתות. הוא מימוש של Grow-MST.
  5. אלגוריתם Prim בונה עץ פורש מינימום מגרף לא-מכוון קשיר בעל טבלת עלויות לקשתות. הוא מימוש של Grow-MST.


הפרק הקודם:
עצים
אלגוריתם Union-Find
תרגילים
הפרק הבא:
אלגוריתמים למציאת עפ"מ