Бинарный поиск

Показываю все и сразу

В бинарном поиске мы используем дробление отсортированного массива на половины.

// Сначала создаем массив и переменную для счета операций. Массив обязательно должен быть отсортирован.
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let count = 0;

// Далее мы создаем функцию с 2 аргументами. Первый - массив в котором ищем и второй - сам элемент который ищем.
function binarySearch(array, item) {

  // Внутри функции мы создаем нужные для работы переменные

  let start = 0; // Начальная позиция массива. Это наш первый элемент(индекс 0)
  let end = array.length; // Конечная позиция. Это наш последний элемент(Вычесляем по длине массива)
  let middle; // Это средний элемент в массиве. Вычеслять будем в цикле ниже.
  let found = false; // Некий флаг который будет показывать нашли мы элемент или нет.
  let position = -1; // И позиция которую мы будем возвращать если нашли элемент, если нет, то возвращаем -1

  // Далее у нас идет цикл while. Цикл будет работать до тех пор пока мы не нашли элемент.

  while (found === false && start <= end) { // если found false и начало меньше и не поровнялось с концом, то ищем дальше
    count++; // С каждой итерацией прибавляем +1 к кол операций.
    middle = Math.floor((start + end) / 2); // Мы берем начало и конец, прибавляем и делим на 2. Так мы находим середину

    if (array[middle] === item) { // Если элемент под индексом middle (наша середина) равен, тому что ищем.
      found = true; // тогда флаг наш в true
      position = middle; // Добавляем наш индекс под которым находится средний элемент в позицию

      return position; // и возвращаем индекс нашего искомого элемента.
    }
    
    if (item < array[middle]) { // если искомый элемент меньше чем элемент под индексом middle(наша середина)
      end = middle - 1; // то мы в переменную где находится конец массива присваиваем нашу середину и отнимаем 1.
    } 
    else { // иначе мы присваиваем середину в переменную где находится начало и прибавляем 1
      start = middle + 1;
    }
  }
  
  return position; // Возвращаем из функции позицию
}

//Выводим в консоль индекс искомого элемента и кол операций требуемых для этого:
console.log(binarySearch(array, 4)); // 3
console.log(count); // 3

Далее я объясню для таких чайников как я!

Смотрим подробно на примере поиска 4 в нашем массиве - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Первая итерация:

Наша переменная start = 0, а end = 10.

let start = 0;
let end = array.length; // 10

Далее запускается цикл while. Так как found у нас false, а 0 меньше чем 10 мы запускаем цикл и ищем середину массива.

while (found === false && start <= end) { 
  middle = Math.floor((start + end) / 2) // наша середина 5. Так как 0 + 10 = 10 / 2 = 5 
  }

Мы нашли середину - это 5. Эта пятерка это индекс,не элемент!
Далее мы проверяем, равен ли элемент под индексом 5 нашему искомому элементу - item

// под индексом 5 у нас 6
if (array[middle] === item) {  // 6 не равно 4, 
      found = true; 
      position = middle; 
      return position; 
    }

В нашем случае у нас под индексом 5 находится 6, а ищем мы 4. В таком случаее мы идем дальше

if (item < array[middle]) { // в item у нас 4 в array[middle] у нас 6
      end = middle - 1; // 4 меньше чем 6. Поэтому выполняем это условие.
      // в переменную end мы кладем значение из middle это 5 и отнимаем 1, значит в end у нас 4.
      // отняли еденицу мы потому что элемент под индексом 5 мы проверили выше в условии (array[middle] === item)
      // мы знаем, что искомый элемент меньше чем элемент под индексом 5. Поэтому все остальное включительно 5 нам не нужно и мы это отрезаем.
    } else {
      start = middle + 1;
    }

Вторая итерация

В переменной start у нас все еще 0, а в end уже 4

let start = 0;
let end = 4;

Далее опять идет цикл:

while (found === false && start <= end) { 
  middle = Math.floor((start + end) / 2) // Теперь 0 + 4 = 4 / 2 = 2
  }

Теперь наша середина middle = 2.
Далее условие:

if (array[middle] === item) { // под индексом 2 в массиве у нас 3.
      found = true; // 3 не равно 4 поэтому идем дальше
      position = middle;

      return position;
    }

Следующее условие:

  if (item < array[middle]) { // 4 больше чем 3
      end = middle - 1;
    } else { // поэтому вполняем это условие
      start = middle + 1; // все также как и было, только теперь мы меняем начальную позицию массива.
      // Выше мы проверили элемент под индексом 2 (array[middle] === item), он нам больше не нужен, поэтому прибавляем +1
    }

Третья итерация

Теперь в переменной start у нас 3, а в end все еще 4

let start = 3;
let end = 4;

Далее цикл:

while (found === false && start <= end) { 
  middle = Math.floor((start + end) / 2) // Теперь 3 + 4 = 7 / 2 = 3
  // 7 / 2 будет 3.5, но метод floor округляет до 3.
  }

Далее опять условие:

if (array[middle] === item) { // под индексом 3 в массиве у нас 4. Искомый элемент тоже 4
      found = true; // 4 равно 4 поэтому выполняем эти условия
      position = middle; // в position кладем 3

      return position; // возвращаем из функции 3
    }

Все конец.

console.log(binarySearch(array, 4)); // 3