Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие часть1.doc
Скачиваний:
24
Добавлен:
01.03.2025
Размер:
6.94 Mб
Скачать

5.3. Бинарный поиск в упорядоченном массиве

Он состоит в последовательном разделении упорядоченного массива пополам, при этом на каждом шаге можно определить, в какой из двух половин находится искомый элемент, сравнив искомый элемент и элемент, который находится в точке деления. При этом локализуется сначала половина массива, затем уже четверть массива и т. д. Процесс продолжается до тех пор, пока в массиве не останется один последний элемент. Если он совпадает с искомым значением, то поиск успешен, в противном случае имеем промах.

Данный алгоритм можно реализовать как итеративно, так и рекурсивно. На практике чаще используется более эффективный итеративный вариант, но рекурсивное решение является хорошей иллюстрацией идеи бинарного поиска.

// рекурсивный вариант функции,

// начальный вызов: seach_bin_r(a, 0, n-1, k);

item seach_bin_r(item a[], int l, int r, T_key k)

{ int m=(l+r)/2;

if (a[m].key==k) return a[m];//искомый элемент на границе

if (l==r) return nullitem;//поиск закончен промахом

if (k<a[m].key) return seach_bin_r(a,l,m-1,k);

else return seach_bin_r(a,m+1,r,k);

}

// нерекурсивный вариант функции бинарного поиска

item seach_bin(item a[], int n, T_key k)

{ int l=0, r=n-1;

while (l<=r)

{ int m=(l+r)/2;

if (k>a[m].key) l=m+1;

else if (k<a[m].key) r=m-1;

else return a[m];

}

return nullitem;

}

Максимальное количество делений массива пополам составляет ближайшее целое, большее log2n , следовательно, асимптотическая оценка сложности поиска O(logn). Например, если в массиве 1000 элементов, то за 10 делений пополам мы уменьшим массив до одного элемента. Поиск может закончиться и раньше, если искомый элемент окажется граничным на каком-то промежуточном шаге.

Попробуем оценить, во что обходится поддержание массива в отсортированном виде. Ведь новый элемент уже нельзя вставить в конец массива, а удаляемый элемент нельзя заменить последним. Действительно, порядок временной сложности вставки становится O(n), время удаления также увеличивается, но асимптотическая оценка остается по-прежнему O(n) (сначала движемся по массиву вперед, чтобы найти нужный элемент, после этого продолжаем движение, перемещая каждый элемент влево).

На практике вопрос о применении данного алгоритма обычно решают путем сравнения количества операций поиска и операций обновления. Если данные обновляются редко, и размер массива велик, то бинарный поиск существенно ускорит производительность всего приложения в целом.

5.4. Бинарные деревья поиска

Проанализировав в целом реализацию поддержки поиска на основе линейной структуры, можно сделать вывод, что любой вариант включает функции с линейной временной сложностью алгоритма. При организации поиска на больших совокупностях данных стоит подумать об отказе от линейной структуры в пользу иерархической. Для этого есть весомые основания — в древовидной структуре, в отличие от линейной, путь от корня к любым данным не превышает высоты дерева, следовательно, имеется реальная возможность вообще избавиться от медленных операций с линейной сложностью.

Бинарное дерево поиска уже упоминалось в предыдущих главах. Напомним, что это упорядоченное бинарное дерево, для каждого узла которого выполняется условие — все левые потомки имеют ключи, меньшие, чем ключ узла, а правые — большие (возможно равные).