Бинарный поиск нужен для быстрого поиска элемента в массиве. При этом можно найти первое или последние вхождение элемента. Для бинарного поиска необходим
отсортированный массив.
Сложность такого алгоритма log2n, n - количество элементов.
Находим значение элемента в середине массива и сравниваем его с ключом. Если ключ меньше значения середины, то поиск осуществляется в первой половине элементов, иначе — во второй. Действия прекращаются, когда мы находим элемент равный ключу или больше не можем подсчитать значение середины, то есть переменная left > right.
Давайте понаблюдаем, как будет выполняться алгоритм на примере. Нам нужно в массиве 1, 2 ... 8 найти число 6.
Первый делом заведем переменные left, right и center - левый, правый и центральный индекс элемента соответственно. Переменные left и right будут обозначать границу поиска, а с центральным
элементом будем проводить сравнения.
Шаг 1.
Изначально left = 0, right = размер массива - 1, центральный элемент будем считать как
center = (left + right) / 2.
Так как наш элемент строго больше чем центральный, то меняем значение левой границы на
left = center + 1. Если бы элемент был меньше чем центральный,
то поменяли бы значение правой границы на right = center - 1.
Шаг 2.
left = 4, right = 7, center = (left + right) / 2. В этот раз center попадает на элемент равный нашему ключу. На этом моменте мы должны закончить наш поиск.
Мы будем выводить yes, если искомый элемент есть в массиве, иначе no.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> int main() { int i, j, key, flag; int left, right, center; int A[8] = { 1,2,3,4,5,6,7,8 }; // массив из примера scanf("%i", &key); // вводим ключ // начало бинарного поиска flag = 0; left = 0; right = 7; while (left <= right) { center = (right + left) / 2; if (A[center] == key) { flag = 1; break; } if (A[center] >= key) { right = center - 1; } else { left = center + 1; } } // конец бинарного поиска if (flag == 1) { printf("yes"); } else { printf("no"); } return 0; }
Как мы видим алгоритм не сложный, но будьте внимательны при его написании.
Давайте посмотрим как искать самое правое вхождение элемента. Будем считать, что хотя бы один такой элемент есть в массиве. На нашем примере будем искать число 2.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> int main() { int i, j, key, flag; int left, right, center; int A[8] = { 2,2,2,3,4,6,7,12 }; // неубывающий массив чисел scanf("%i", &key); // вводим ключ // начало бинарного поиска flag = 0; left = 0; right = 7; while (left <= right) { center = (right + left) / 2; if (A[center] > key) { right = center - 1; } else { left = center + 1; } } // конец бинарного поиска printf("%i", right); return 0; }
Чтобы найти самое левое вхождение, нужно изменить условие в строке 16 на A[center] >= key. А в строке 25 нужно выводить не right, а left.
Code.C
© Copyright Павел Калашников 2021
обратная связь code.c04@mail.ru