2017-08-28 2 views
1

Ich habe versucht, den binären Suchalgorithmus in meinem Codebeispiel zu verwenden, aber es läuft nicht wie erwartet. Ich weiß nicht warum. Bitte erläutern Sie mirBinäre Suche nicht ausgeführt?

var array = [1, 4, 6, 8, 9, 12, 15, 17, 19, 34, 55, 78, 80]; 

function binarySearch (array, numberToSearch) { 
var firstIndex = 0; 
var lastIndex = array.length - 1; 
var currentIndex; 
var currentElement; 

currentIndex = (lastIndex + firstIndex)/2 | 2; 
currentElement = array[currentIndex]; 

while (firstIndex <= lastIndex) { 
    if (numberToSearch === currentElement) { 
     // found 
     console.log(currentIndex); 
     return currentIndex; 
    } else if (numberToSearch < currentElement) { 
     lastIndex = currentIndex - 1; 
     currentIndex = (lastIndex + firstIndex)/2 | 2; 
     currentElement = array[currentIndex]; 
    } else if (numberToSearch > currentElement) { 
     firstIndex = currentIndex + 1; 
     currentIndex = (lastIndex + firstIndex)/2 | 2; 
     currentElement = array[currentIndex]; 
    } 
} 
return -1; 
} 
binarySearch(array, 12); 

Ich drucke sollte: 5, aber nichts passiert

+1

Ich denke, Sie Binary Suche nicht Binary Art gemeint? – abhishekkannojia

+0

Ich denke, dass Sie nicht zulassen, dass die Schleife mit diesen Returns -1 vollständig ausgeführt wird. Ich denke, Sie mischen eine iterative Lösung mit einer rekursiven Lösung. – 82Tuskers

+0

@ 82Tuskers Ich gebe -1 für die No-Results-Bedingung zurück. Aber ich denke, es ist nicht das Problem –

Antwort

1

Was mit Ihrem Code falsch ist:

  1. Es sollte var currentIndex = (lastIndex + firstIndex)/2 | 0; (nicht | 2);

  2. currentIndex und currentElement sollte bei jeder Iteration innerhalb der Schleife berechnet werden.

Also, das ist die korrigierte Version des Codes:

var array = [1, 4, 6, 8, 9, 12, 15, 17, 19, 34, 55, 78, 80]; 
 

 
function binarySearch (array, numberToSearch) { 
 
var firstIndex = 0; 
 
var lastIndex = array.length - 1; 
 

 
while (firstIndex <= lastIndex) { 
 
    var currentIndex = (lastIndex + firstIndex)/2 | 0; 
 
    var currentElement = array[currentIndex]; 
 
    if (numberToSearch === currentElement) { 
 
     return currentIndex; 
 
    } else if (numberToSearch < currentElement) { 
 
     lastIndex = currentIndex - 1; 
 
    } else if (numberToSearch > currentElement) { 
 
     firstIndex = currentIndex + 1; 
 
    } 
 
} 
 
return -1; 
 
} 
 

 
console.log(binarySearch(array, 99)); // -1 
 
console.log(binarySearch(array, 12)); // 5

BTW, das var currentIndex = (lastIndex + firstIndex)/2 | 0; sieht ganz ungewöhnlich. Der gemeinsame Weg ist var currentIndex = Math.floor((lastIndex + firstIndex)/2);

+1

Obwohl 'var currentIndex = (lastIndex + firstIndex)/2 | 0; 'scheint Ihnen unbekannt, es ist das [optimalste] (https://jsperf.com/jsfvsbitnot/8). Sie sollten gute Praktiken nicht ablehnen. –

+1

Ich bin mir sicher, dass Sie Recht haben, aber es ist nicht sehr häufig in einem solchen Kontext in JS verwendet - ich meine, es ist nicht etwas, was jeder kennt und versteht und die Optimierung selbst ist kaum wahrnehmbar. Also bevorzuge ich klarere Dinge. – curveball

+0

BTW, nachdem ich ein Video von Douglas Crockford gesehen habe, wo er Leute aus C++ etc. warnt, die in JS Bit Operatoren unterschiedliche Kosten haben und er nicht empfiehlt, sie zu verwenden, es sei denn, sie sind das, was Sie eigentlich wollen. – curveball

1

Zunächst einmal, was der Punkt der bitweise ist OR hier:

currentIndex = (lastIndex + firstIndex)/2 | 2; 

denke ich es sein sollte:

currentIndex = (lastIndex + firstIndex)/2; 

Es gibt grundlegende Fehler auf der Suche Speicherplatzupdate. Wenn numberToSearch < currentElement bedeutet das middle element (Element bei Index Momentan) größer ist als Nummer gesucht werden daher richtig neue Grenzen sind:

lastIndex = currentIndex - 1; 

Auch wenn numberToSearch > currentElement bedeutet das middle element (Element bei Index Momentan) ist kleiner als zu durchsuchende Anzahl, daher richtig neue Grenzen sind:

firstIndex = currentIndex + 1; 
Daher

, der richtige Code ist:

var array = [1, 4, 6, 8, 9, 12, 15, 17, 19, 34, 55, 78, 80]; 

function binarySearch (array, numberToSearch) { 
var firstIndex = 0; 
var lastIndex = array.length - 1; 
var currentIndex; 
var currentElement; 

currentIndex = (lastIndex + firstIndex)/2; 
currentElement = array[currentIndex]; 

while (firstIndex <= lastIndex) { 
    if (numberToSearch === currentElement) { 
     // found 
     console.log(currentIndex); 
     return currentIndex; 
    } else if (numberToSearch < currentElement) { 
     lastIndex = currentIndex - 1; 
     currentIndex = (lastIndex + firstIndex)/2 | 2; 
     currentElement = array[currentIndex]; 
    } else if (numberToSearch > currentElement) { 
     firstIndex = currentIndex + 1; 
     currentIndex = (lastIndex + firstIndex)/2 | 2; 
     currentElement = array[currentIndex]; 
    } 
} 
return -1; 
} 
binarySearch(array, 12); 
+0

Oh, ich sehe meinen Fehler im Logikcode :). Ich habe es bearbeitet, aber Sie wissen, immer noch nicht das Ergebnis. Sie können versuchen, diesen Code auf Ihrem Computer auszuführen. Die Logik ist wahr. –

+1

Er war anfangs richtig, wenn er 'Math.floor()' nicht verwendete. Die Methode, die er benutzte, ist manchmal schneller (https://jsperf.com/jsfvsbitnot/8), sollte aber 0, nicht 2 sein. –

1

Hier ist Ihre korrigierte Antwort mit all den Orten, die ich aktualisiert. Du warst ziemlich nah dran! Es schien, als ob Sie die iterative Version von Binary Search mit der recursive Lösung kombinierten.

CodePen Demo

var array = [1, 4, 6, 8, 9, 12, 15, 17, 19, 34, 55, 78, 80]; 

function binarySearch (array, numberToSearch) { 
    var firstIndex = 0; 
    var lastIndex = array.length - 1; 
    var currentIndex; 
    var currentElement; 

    while (firstIndex <= lastIndex) { 
    currentIndex = (lastIndex + firstIndex)/2 | 0; //should default to zero, not Two! 
    currentElement = array[currentIndex];//These should both update every iteration so it does not infinitely loop! 
    if (numberToSearch === currentElement) { 
     // found 
     console.log(currentIndex); 
     return currentIndex; 
    }else if (numberToSearch < currentElement) { 
     lastIndex = currentIndex - 1; //If current is too big, move right pointer to the left 
    }else if (numberToSearch > currentElement) { 
     firstIndex = currentIndex + 1;//If current is too small, move left pointer to the right 
    } 
    } 
    return -1;//When condition of while it broken and no solution has been found, return -1 to indicate it is not in the array 
} 
binarySearch(array, 12) //5 

wird weiter durch optimiert nicht mit Math.floor() als number | 0is sometimes faster.

+0

Sehr sauber !. Danke, dass du Zeit für mein Problem verbringst :) –