שאלת מבחן במבני נתונים - אוניברסיטת בר-אילן 2021 - חיפוש בינארי

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

לדוגמא: המערך הבא הוא מערך ממוין מעגלי כאשר .



א. כתוב/י אלגוריתם המקבל מערך עם איברים שונים ממוין באופן מעגלי ואינדקס ומחזיר 0 אם האיבר הגדול ביותר במערך נמצא משמאל לאינדקס (כולל, ז"א ב-) אחרת, יחזיר 1. זמן הריצה .
ב. כתוב/י אלגוריתם המקבל מערך
עם איברים שונים ממוין באופן מעגלי ומחזיר את מספר ההזזות המעגליות שיש לבצע על מנת שהמערך יהיה ממוין מהקטן לגדול. זמן הריצה הדרוש .
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
אוניברסיטת בר-אילןמועד ב · 2021 · סמסטר ב
★★★★★
חיפוש בינאריסיבוכיות זמןרקורסיהנוסחת נסיגההוכחת נכונות
סעיף א': בדקו את היחס בין האיבר הראשון לבין האיבר . מה ניתן להסיק מכך על מיקום ה'שבר' במערך המעגלי? סעיף ב': מספר ההזזות תלוי במיקום האיבר הקטן ביותר. השתמשו בחיפוש בינארי כדי למצוא אותו ביעילות.
חלק א' — בדיקת מיקום המקסימום ב-


תצפית מבנית: במערך ממוין מעגלי עם הזזה , קיים "נקודת שבירה" יחידה:



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

האלגוריתם:

MAX_LOCATION(A, n, i):
  if A[1] < A[n]:          // k=0, המערך ממוין כבר, מקסימום ב-A[n]
    if i == n: return 0
    else:      return 1
  // כאן A[1] > A[n], קיימת הזזה k > 0
  if A[i] < A[1]:          // A[i] בצד הימני (i > k), המקסימום נמצא ב-A[1..k] ⊆ A[1..i]
    return 0
  // A[i] ≥ A[1], כלומר i בצד השמאלי (i ≤ k)
  if i < n and A[i] < A[i+1]:  // עדיין לא הגענו לנקודת השבירה
    return 1
  else:                    // A[i] > A[i+1] או i=n ← A[i] הוא המקסימום
    return 0


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

דוגמה: על עם : , , ו- ← מחזיר 0 ✓. עבור : ← מחזיר 1 ✓.

---
חלק ב' — מציאת מספר ההזזות ב-


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

תכונה לחיפוש בינארי: לכל :



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

האלגוריתם:

FIND_ROTATIONS(A, n):
  if A[1] < A[n]:     // המערך ממוין כבר
    return 0
  lo ← 1,  hi ← n
  while lo < hi:
    mid ← ⌊(lo + hi + 1) / 2⌋
    if A[mid] > A[n]:
      lo ← mid        // נקודת השבירה נמצאת ב-[mid, hi]
    else:
      hi ← mid - 1    // נקודת השבירה נמצאת ב-[lo, mid-1]
  return lo           // lo = k


נכונות: בכל איטרציה נשמר אינווריאנט: .
  • אם אז , לכן נעדכן .
  • אם אז (כי עצמו שייך לצד הימני), לכן .


הלולאה מסתיימת כאשר .

מעקב על הדוגמה: , , :

פעולה
1745 < 12
13265 > 12
2333 < 12
22——מחזיר 2 ✓


סיבוכיות: בכל איטרציה מחצים את הטווח , לכן זמן הריצה הוא .