מבני נתונים ואלגוריתמים - מחברת קורס/שיעורי בית 9/שאלות

מתוך ויקיספר, אוסף הספרים והמדריכים החופשי


שימו לב:

*נא להגיש רק את שאלות 1-5.
  • שאר השאלות הן לצורך חזרה למבחן בלבד. אין צורך להגיש את התשובות להן.

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


1[עריכה]

נתון גרף לא-מכוון וקשיר בייצוג רשימה, וטבלת עלויות לקשתות Edge-Costs.‏ הוא מספר שלם חיובי כלשהו, שאינו גדל עם שאר נתוני הבעיה (כגון מספר הצמתים והקשתות). ידוע שלכל קשת מחיר בתחום . אנא מצא אלגוריתם יעיל למציאת עץ פורש מינימום בגרף כגון זה.

2[עריכה]

נתון גרף לא-מכוון וקשיר , וכן טבלת עלויות על הקשתות Edge-Costs.


הגדרה:

קבוצת קשתות היא קבוצת קשתות היזון חוזר אם לאחר הסרתה, חסר מעגלים; במילים אחרות, הקבוצה היא קבוצת קשתות היזון חוזר אם הוא יער.


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


רמז

אל תתמקד בקבוצה , אלא בקבוצה המשלימה אותה, . אם היא קבוצת קשתות ההיזון החוזר הזולה ביותר - מהי ?‏ אם היא קבוצת קשתות ההיזון החוזר הזולה ביותר - איך תוכל למצוא את הקבוצה המשלימה לה ביעילות?

3[עריכה]

להלן גרסה של אלגוריתם החיפוש הרוחבי:

BFS(G, s)
1	q = Make-Queue()

2	Visited = Make-Array( |V| )

3	for u in V
4		Visited[u] = False

5	Print s
6	Visited[s] = True
7	Enqueue(q, s)

8	while not Empty(q)
9		u = Dequeue(q)
	
10		For every neighbor v of u
11			if Visited[v] == False
12				Print v
13				Visited[v] = True
14				Enqueue(q, v)

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

להלן גרף שבו צומת המוצא הוא .

בעיית החיפוש הרוחבי.
בעיית החיפוש הרוחבי.

הנח שבשורה 10, אם לצומת יש יותר משכן יחיד, סדר הצמתים הוא כסדרם המספרי.

  1. באיזה סדר יודפסו האיברים?
  2. נניח ש קשיר מ (יש מסלול מ לכל צומת). אנא הוכח שהאלגוריתם יעבוד בזמן .


4[עריכה]

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

  1. האם זמן הריצה הוא בהכרח ?
  2. האם ייתכן שזמן הריצה הוא ?



5[עריכה]

נתון טיפוס אבסטרקטי "שק" בעל הממשק הבא:

#Makes a new sack.
Make-Sack()

# Inserts an element (v) to a sack (ks).
Insert(k, v)

# Returns whether the sack is empty.
Empty(k)

# Deletes *some* element from a (non-empty) sack (k) and returns the value of 
#	the deleted element.
Delete(k)

זהו מבנה נתונים דומה לתור, אלא שהפעולה Insert מכניסה איבר, והפעולה Delete שולפת (ומחזירה) איבר כלשהו, לאו דווקא האיבר הראשון שהוכנס.

להלן ווריאציה אפשרית של אלגוריתם החיפוש הרוחבי, אך כעת עם שק במקום תור:

Sack-Search(G, s)
1	k = Make-Sack()

2	Visited = Make-Array( |V| )

3	for u in V
4		Visited[u] = False

5	Print s
6	Visited[s] = True
7	Insert(k, s)

8	while not Empty(q)
9		u = Delete(k)
	
10		For every neighbor v of u
11			if Visited[v] == False
12				Print v
13				Visited[v] = True
14				Insert(k, v)

נניח שהגרף קשיר מ (יש מסלול מ לכל צומת).

  1. האם Sack-Search בהכרח ידפיס כל צומת בדיוק פעם יחידה?
  2. האם סדר ההדפסות בהכרח יהיה לפי מרחק הצמתים מ?

6[עריכה]

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

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