Implementierung der binären Suche in JavaScript
Sie durchsuchen ein sortiertes Array mit 100.000 Produktpreisen. Die in JavaScript integrierte Methode indexOf() prüft jedes Element von Anfang an — das sind potenziell 100.000 Vergleiche. Die binäre Suche schafft es in maximal 17. Dieser Unterschied zeigt, warum der JavaScript-Algorithmus für binäre Suche wichtig ist und warum es sich lohnt, ihn selbst zu schreiben — denn JavaScript bietet keine integrierte Methode für binäre Suche.
Dieser Artikel behandelt die Funktionsweise der binären Suche, wie man sowohl iterative als auch rekursive Versionen implementiert und wann man sie gegenüber der linearen Suche verwenden sollte.
Wichtigste Erkenntnisse
- Die binäre Suche funktioniert nur bei sortierten Arrays und läuft in O(log n) Zeit, verglichen mit O(n) bei der linearen Suche.
- Der iterative Ansatz wird für die meisten Anwendungsfälle bevorzugt — er ist lesbar, effizient und verwendet O(1) Speicherplatz.
- Die rekursive Version ist elegant, verbraucht aber O(log n) Stack-Speicher, und das Vergessen des
returnbeim rekursiven Aufruf ist ein häufiger Fehler. - Sortieren Sie Zahlen-Arrays immer mit einem numerischen Komparator (
(a, b) => a - b), bevor Sie die binäre Suche anwenden — JavaScripts Standard-sort()ist lexikografisch.
Was ist binäre Suche und warum erfordert sie ein sortiertes Array?
Die binäre Suche ist ein Divide-and-Conquer-Algorithmus. Sie funktioniert, indem sie den Suchraum wiederholt halbiert, bis sie den Zielwert findet oder alle Möglichkeiten ausgeschöpft sind.
Der Haken dabei: Sie funktioniert nur bei sortierten Arrays. Der Algorithmus geht davon aus, dass sich das Ziel in der rechten Hälfte befinden muss, wenn es größer als das mittlere Element ist. Diese Annahme bricht bei unsortierten Daten vollständig zusammen — Sie würden falsche Ergebnisse ohne Fehlermeldung erhalten.
Die Schritte sind:
- Finden Sie das mittlere Element des aktuellen Suchbereichs
- Wenn es dem Ziel entspricht, geben Sie seinen Index zurück
- Wenn das Ziel kleiner ist, durchsuchen Sie die linke Hälfte
- Wenn das Ziel größer ist, durchsuchen Sie die rechte Hälfte
- Wiederholen Sie den Vorgang, bis es gefunden wird oder der Suchbereich leer ist
Implementierung der binären Suche in JavaScript: Iterativer Ansatz
Die iterative Version verwendet eine while-Schleife und zwei Zeiger. Sie ist der bevorzugte Ansatz für die meisten Fälle — lesbar, effizient und verwendet O(1) Speicherplatz.
function binarySearch(arr, target) {
let start = 0
let end = arr.length - 1
while (start <= end) {
const mid = Math.floor((start + end) / 2)
if (arr[mid] === target) {
return mid // Return the index
} else if (arr[mid] < target) {
start = mid + 1 // Search right half
} else {
end = mid - 1 // Search left half
}
}
return -1 // Target not found
}
const prices = [10, 25, 47, 89, 134, 200]
console.log(binarySearch(prices, 89)) // 3
console.log(binarySearch(prices, 50)) // -1
Beachten Sie, dass dies den Index des Ziels zurückgibt, nicht einen Boolean-Wert. Das ist in der Praxis fast immer nützlicher.
Rekursive binäre Suche in JavaScript
Die rekursive Version übergibt bei jedem Aufruf aktualisierte Grenzindizes. Sie ist elegant, verwendet aber O(log n) Stack-Speicher — einen Frame pro rekursivem Aufruf.
function binarySearchRecursive(arr, target, start = 0, end = arr.length - 1) {
if (start > end) return -1
const mid = Math.floor((start + end) / 2)
if (arr[mid] === target) return mid
return arr[mid] < target
? binarySearchRecursive(arr, target, mid + 1, end)
: binarySearchRecursive(arr, target, start, mid - 1)
}
const scores = [3, 11, 22, 45, 67, 91]
console.log(binarySearchRecursive(scores, 22)) // 2
console.log(binarySearchRecursive(scores, 50)) // -1
Ein häufiger Fehler: Das Vergessen des return beim rekursiven Aufruf. Ohne dieses gibt die Funktion undefined zurück, selbst wenn das Element existiert.
Discover how at OpenReplay.com.
Sortieren vor der Suche
Wenn Ihr Array noch nicht sortiert ist, müssen Sie es zuerst sortieren. JavaScripts Standard-Array.sort() sortiert lexikografisch, was numerische Vergleiche zunichte macht:
[10, 9, 100].sort() // [10, 100, 9] — falsch
[10, 9, 100].sort((a, b) => a - b) // [9, 10, 100] — richtig
Verwenden Sie immer einen numerischen Komparator für Zahlen-Arrays, bevor Sie die binäre Suche ausführen.
Binäre Suche vs. lineare Suche: Wann welche verwenden?
| Lineare Suche | Binäre Suche | |
|---|---|---|
| Array muss sortiert sein | Nein | Ja |
| Zeitkomplexität | O(n) | O(log n) |
| Am besten für kleine Arrays | ✅ | ❌ |
| Am besten für große Arrays | ❌ | ✅ |
| Mehrfache Suchen | Ineffizient | Effizient |
Bei einem Array mit 10.000 Elementen benötigt die lineare Suche bis zu 10.000 Vergleiche. Die binäre Suche benötigt maximal 14. Wenn Sie einmal durch ein kleines, unsortiertes Array suchen, ist indexOf() in Ordnung. Wenn Sie wiederholt durch große sortierte Daten suchen, ist die binäre Suche das richtige Werkzeug.
Fazit
Die binäre Suche ist in JavaScript einfach zu implementieren, sobald Sie die Anforderung an sortierte Arrays verstanden haben. Verwenden Sie standardmäßig die iterative Version — sie ist übersichtlicher und vermeidet den Overhead des Call-Stacks. Verwenden Sie die rekursive Version, wenn die Struktur Ihres Codes davon profitiert, aber denken Sie daran, immer den rekursiven Aufruf mit return zurückzugeben. Und überprüfen Sie immer, ob Ihr Array mit einem geeigneten numerischen Komparator sortiert ist, bevor Sie suchen.
Häufig gestellte Fragen (FAQs)
Ja, die binäre Suche funktioniert mit String-Arrays, solange diese alphabetisch sortiert sind. Die Vergleichsoperatoren in JavaScript behandeln String-Vergleiche standardmäßig lexikografisch, sodass die gleiche Algorithmuslogik gilt. Stellen Sie nur sicher, dass das Array mit der Standard-Sortiermethode sortiert ist, die Strings bereits in lexikografischer Reihenfolge sortiert.
JavaScript-Arrays sind so konzipiert, dass sie flexibel sind und gemischte Typen enthalten können, was eine integrierte binäre Suche unpraktisch macht, da sie eine sortierte, einheitlich typisierte Sammlung erfordert. Bibliotheken wie Lodash bieten sortedIndexOf für diesen Zweck, aber für Vanilla-JavaScript müssen Sie Ihre eigene Implementierung schreiben.
Die Standardimplementierung gibt den Index eines übereinstimmenden Elements zurück, aber nicht unbedingt das erste oder letzte Vorkommen. Wenn Sie den ersten oder letzten Index eines doppelten Werts benötigen, müssen Sie den Algorithmus so ändern, dass er auch nach dem Finden einer Übereinstimmung weiter in der linken oder rechten Hälfte sucht.
Beide haben die gleiche O(log n) Zeitkomplexität, sodass ihre Rohgeschwindigkeit nahezu identisch ist. Die iterative Version vermeidet jedoch den Overhead rekursiver Funktionsaufrufe und verwendet konstanten Speicher, was sie in der Praxis etwas effizienter macht. Bei sehr tiefen Rekursionen kann die rekursive Version auch einen Stack-Overflow riskieren.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.