Menu
Coddy logo textTech

Binary Search (חיפוש בינארי)

עודכן לאחרונה

חיפוש בינארי מוצא ערך מטרה במערך **ממוין** על ידי חציית חלון החיפוש שוב ושוב. הוא משווה את האיבר האמצעי למטרה: התאמה מסיימת את החיפוש; אחרת, החצי שלא יכול להכיל את המטרה נזרק והחלון מצטמצם לחצי השני. כל השוואה מוציאה מהמשחק חצי מהאיברים שנותרו, ולכן הוא רץ ב-O(log n): חיפוש במיליון ערכים ממוינים דורש לכל היותר כ-20 השוואות.

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

סיבוכיות זמן וזיכרון

מקרהסיבוכיותהערות
המקרה הטובO(1)האיבר האמצעי הוא המטרה כבר בהשוואה הראשונה.
המקרה הממוצעO(log n)כל השוואה חוצה את החלון שנותר.
המקרה הגרועO(log n)החלון מצטמצם לאיבר יחיד לפני התאמה או החטאה.
זיכרוןO(1)הגרסה האיטרטיבית שומרת רק את האינדקסים lo, hi ו-mid.

צעד אחר צעד

צעדמה קורה
1קובעים את lo לאינדקס הראשון ואת hi לאינדקס האחרון של המערך הממוין.
2מחשבים את האינדקס האמצעי: mid = (lo + hi) // 2.
3אם a[mid] שווה למטרה, מחזירים את mid (נמצא).
4אם a[mid] **קטן** מהמטרה, המטרה יכולה להיות רק בחצי הימני: lo = mid + 1.
5אם a[mid] **גדול** מהמטרה, מחפשים בחצי השמאלי: hi = mid - 1.
6חוזרים לצעד 2 כל עוד lo <= hi; אם החלון מתרוקן, המטרה לא נמצאת במערך.

דוגמה מפורטת

חיפוש של 5 ב-[1, 2, 3, 5, 7, 8, 9]:

סבבחלון (lo..hi)mida[mid]פעולה
1[1, 2, 3, 5, 7, 8, 9] (0..6)35a[3] = 5: המטרה נמצאה באינדקס 3.

החטאה, צעד אחר צעד

חיפוש של 4 באותו מערך מראה איך החלון מתרוקן:

סבבחלון (lo..hi)mida[mid]פעולה
10..6355 > 4: מחפשים בחצי השמאלי, hi = 2.
20..2122 < 4: מחפשים בחצי הימני, lo = 2.
32..2233 < 4, ולכן lo הופך ל-3 והחלון מתרוקן: לא נמצא.

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

השתמשו בו כאשרהימנעו ממנו כאשר
הנתונים כבר ממוינים (או שמחפשים בהם פעמים רבות)הנתונים לא ממוינים ומחפשים בהם רק פעם אחת (מיון קודם עולה O(n log n))
האוסף תומך בגישה אקראית מהירה (מערכים)יש רק גישה סדרתית (רשימות מקושרות)
כמות הנתונים גדולה (O(log n) בולט בקנה מידה גדול)כמות הנתונים זעירה (סריקה פשוטה מהירה באותה מידה ופשוטה יותר)

מימוש נקי של Binary Search שאפשר להריץ, ב-Python, JavaScript, Java, C++, C, Pseudocode. בחרו שפה, העתיקו את הקוד, או פתחו אותו טעון מראש בעורך האונליין של Coddy.

קוד Binary Search ב-Python

Python
1def binary_search(a, target):2    lo, hi = 0, len(a) - 13    while lo <= hi:4        mid = (lo + hi) // 25        if a[mid] == target:6            return mid7        if a[mid] < target:8            lo = mid + 1  # search the right half9        else:10            hi = mid - 1  # search the left half11    return -112
13
14nums = [1, 2, 3, 5, 7, 8, 9]  # must be sorted15print("Index of 5:", binary_search(nums, 5))16print("Index of 4:", binary_search(nums, 4))
להריץ את הקוד הזה בעורך ה-Python אונליין

שאלות נפוצות על חיפוש בינארי

מהי סיבוכיות הזמן של חיפוש בינארי?
O(log n) במקרה הממוצע ובמקרה הגרוע, כי כל השוואה חוצה את חלון החיפוש שנותר, ו-O(1) במקרה הטוב, כשהאיבר האמצעי הראשון הוא המטרה. הגרסה האיטרטיבית משתמשת ב-O(1) זיכרון נוסף.
למה חיפוש בינארי דורש מערך ממוין?
צעד החציה נשען על הסדר: השוואת המטרה לאיבר האמצעי אומרת לכם איזה חצי לזרוק רק אם כל מה שמשמאל לאמצע קטן יותר וכל מה שמימינו גדול יותר. על נתונים לא ממוינים ההסקה הזו לא תקפה, ולכן השתמשו בחיפוש ליניארי במקום, או מיינו קודם.
מה ההבדל בין חיפוש בינארי לחיפוש ליניארי?
חיפוש ליניארי סורק איברים אחד אחד (O(n)) ועובד על כל מערך; חיפוש בינארי חוצה את חלון החיפוש של מערך ממוין (O(log n)) אבל דורש קלט ממוין. עבור קומץ פריטים ההבדל זניח; בקנה מידה גדול חיפוש בינארי מנצח בגדול.
כמה השוואות צריך חיפוש בינארי?
לכל היותר בערך log2(n) + 1: עשר השוואות מכסות 1,000 איברים, ועשרים השוואות מכסות 1,000,000. הגדילה הלוגריתמית הזו היא מה שהופך אותו לדרך החיפוש המוגדרת כברירת מחדל על נתונים ממוינים.
מהו באג הגלישה הקלאסי בחיפוש בינארי?
חישוב האמצע כ-(lo + hi) / 2 יכול לגרום לגלישה במספרים שלמים בגודל קבוע כש-lo + hi חורג מהערך המקסימלי של הטיפוס. הצורה הבטוחה היא mid = lo + (hi - lo) / 2. ב-Python זה לא משנה (מספרים שלמים בדיוק שרירותי), אבל ב-Java, C ו-C++ זה באג אמיתי ומפורסם.
האם חיפוש בינארי זהה לעץ חיפוש בינארי?
הם חולקים את רעיון החציה אבל שונים במבנה: חיפוש בינארי הוא אלגוריתם על מערך ממוין, ואילו עץ חיפוש בינארי הוא מבנה נתונים מקושר ששומר את המפתחות שלו מסודרים, כך שחיפוש יורד שמאלה או ימינה בכל צומת.
איור של שפות התכנות ב-Coddy

לשלוט באלגוריתמים עם Coddy

להתחיל