Я попытался использовать алгоритм двоичного поиска в моем примере кода, но он не работает, как я ожидал. Я не знаю почему. Пожалуйста, объясните мне

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);

Я должен напечатать: 5, но ничего не происходит

1
Keitaro Urashima 28 Авг 2017 в 12:49

3 ответа

Лучший ответ

Что не так с вашим кодом:

  1. Это должно быть var currentIndex = (lastIndex + firstIndex) / 2 | 0; (не | 2);

  2. currentIndex и currentElement должны быть рассчитаны для каждого итерация внутри цикла.

Итак, это исправленная версия вашего кода:

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

Кстати, это var currentIndex = (lastIndex + firstIndex) / 2 | 0; выглядит довольно необычно. Обычный способ - var currentIndex = Math.floor((lastIndex + firstIndex) / 2);

1
curveball 28 Авг 2017 в 10:36

Прежде всего, какой смысл побитового OR здесь:

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

Я думаю, что это должно быть:

currentIndex = (lastIndex + firstIndex) / 2;

В обновлении пространства поиска есть основной недостаток . Когда numberToSearch < currentElement означает, что middle element (элемент в индексе currentIndex ) больше числа для поиска, следовательно, правильные новые границы :

lastIndex = currentIndex - 1;

Также, когда numberToSearch > currentElement означает, что middle element (элемент в индексе currentIndex ) меньше числа для поиска, следовательно, правильные новые границы :

firstIndex = currentIndex + 1;

Следовательно, правильный код:

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);
1
Sumeet 28 Авг 2017 в 10:09

Вот ваш исправленный ответ со всеми местами, которые я обновил. Вы были довольно близко! Казалось, что вы объединяете итеративный версия двоичного поиска с рекурсивным решением ,

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

Кроме того, он не использует Math.floor(), поскольку number | 0 является иногда быстрее.

1
Francisco Flores 28 Авг 2017 в 10:34