הרעיון
תנאי מקדים: המערך חייב להיות ממוין (בסדר עולה).
- הגדר
low = 0ו-high = length - 1. - חשב
mid = (low + high) / 2. - אם
arr[mid] == key– מצאנו! מחזירים mid. - אם
arr[mid] < key– הערך בחצי הימני:low = mid + 1. - אם
arr[mid] > key– הערך בחצי השמאלי:high = mid - 1. - חוזרים ל-2 כל עוד
low ≤ high.
דוגמה מצוירת
חיפוש הערך 23 במערך {2, 5, 8, 12, 16, 23, 38, 56, 72, 91}:
| שלב | low | high | mid | arr[mid] | החלטה |
|---|---|---|---|---|---|
| 1 | 0 | 9 | 4 | 16 | 16 < 23 → low = 5 |
| 2 | 5 | 9 | 7 | 56 | 56 > 23 → high = 6 |
| 3 | 5 | 6 | 5 | 23 | 23 == 23 → נמצא! |
מצאנו את 23 באינדקס 5 תוך 3 צעדים בלבד (במקום עד 10 בחיפוש לינארי).
קוד – חיפוש בינארי איטרטיבי
public static int binarySearch(int[] arr, int key) { int low = 0; int high = arr.length - 1; while (low <= high) { int mid = (low + high) / 2; if (arr[mid] == key) return mid; else if (arr[mid] < key) low = mid + 1; else high = mid - 1; } return -1; // לא נמצא }
קוד – חיפוש בינארי רקורסיבי
public static int binarySearchRec(int[] arr, int key, int low, int high) { if (low > high) return -1; int mid = (low + high) / 2; if (arr[mid] == key) return mid; else if (arr[mid] < key) return binarySearchRec(arr, key, mid + 1, high); else return binarySearchRec(arr, key, low, mid - 1); }
קריאה: binarySearchRec(arr, key, 0, arr.length - 1)
סיבוכיות
| מקרה | סיבוכיות | הסבר |
|---|---|---|
| מקרה טוב | O(1) | הערך בדיוק באמצע |
| מקרה גרוע | O(log₂ n) | מחצים את הטווח עד שנשאר איבר אחד |
דוגמאות מספריות
| גודל מערך (n) | צעדים מקסימליים |
|---|---|
| 10 | 4 |
| 100 | 7 |
| 1,000 | 10 |
| 1,000,000 | 20 |
השוואה – לינארי מול בינארי
| חיפוש לינארי | חיפוש בינארי | |
|---|---|---|
| סיבוכיות | O(n) | O(log n) |
| דורש מיון | לא | כן |
| פשטות | פשוט מאוד | מורכב יותר |
| מתאים ל... | מערכים קטנים / לא ממוינים | מערכים גדולים וממוינים |
שאלות נפוצות
מה קורה אם המערך לא ממוין?
חיפוש בינארי לא יעבוד נכון על מערך לא ממוין. התוצאה עלולה להיות שגויה. חובה למיין לפני החיפוש.
למה low <= high ולא low < high?
כי יכול להיות שהערך נמצא כשנשאר בדיוק איבר אחד (low == high). אם נכתוב < במקום <= נפספס את האיבר הזה.
למה mid = (low + high) / 2?
זה האינדקס האמצעי בין low ל-high. חילוק שלמים ב-Java מעגל כלפי מטה. שימו לב: עבור מערכים ענקיים (בלי קשר לבגרות), עדיף low + (high - low) / 2 כדי למנוע גלישה.