Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции_ТП.doc
Скачиваний:
36
Добавлен:
29.03.2015
Размер:
1.63 Mб
Скачать
    1. Бинарный поиск

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

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

low=l; hi=n; search = 0;

while (low<=hi)

{

mid=(low + hi)/2;

if (key= = k[mid])

{

search = mid;

cout<<”Элемент найден.Его номер=”<< mid;

return 0;

}

else

{

if ( key<k[mid]) hi =mid-1;

else low = mid+1;

}

}

Каждое сравнение в бинарном поиске уменьшает число возможных кандидатов сравнения в 2 раза. Таким образом, максимальное число сравнений ключа, которые будут сделаны, составляет приблизительно log2n, т.е. алгоритм бинарного поиска имеет порядок O(log2n).

Отметим, что бинарный поиск может быть использован вместе с индексно-последовательной организацией таблицы и вместо последовательного поиска по индексу может быть использован бинарный поиск. Бинарный поиск может быть также использован при поиске в основной таблице, когда идентифицированы две граничные записи. Бинарный поиск практически бесполезен в ситуациях, где имеется много вставок или удалений.

Сбалансированные деревья (AVL-деревья)

Для удобства определим высоту пустого дерева как 0.

Баланс некоторого узла в дереве определяется как высота его левого поддерева минус высота его правого поддерева.

Сбалансированным бинарным деревом (деревом AVL) является такое бинарное дерево, у которого абсолютное значение баланса каждого узла 1.

Рис. 4.3. Сбалансированное бинарное дерево

    1. Поиск по дереву

Ранее мы рассматривали построение бинарного дерева, в котором все левосторонние потомки некоторого узла с ключом key имели ключи, которые < key, а все правосторонние потомки имели ключи >= key [3].

Прохождение такого бинарного дерева в симметричном порядке дает файл, упорядоченный по возрастанию значения ключа. Такое дерево может быть использовано для бинарного поиска. Алгоритм поиска ключа key в бинарном дереве представляется следующим образом. Предполагаем, что каждый узел дерева содержит четыре поля: поле k, в котором хранится значение ключа данной записи; поле r, в котором хранится сама запись; поля left и right, которые являются указателями на поддеревья:

class item

{

public:

item *left; item *right ;

int k; char r;

};

void main()

{

item * p; // создается объект р

item * search=NULL;

while( p!=NULL)

{

if (p->k==key) search=p;

if( p->k>key) p=p->left;

if (p->k<key) p=p->right;

}

Отметим, что бинарный поиск фактически использует отсортированный массив как некоторое неявное дерево бинарного поиска. Средний элемент этого массива можно представить как корень такого дерева. Левую (верхнюю) половину массива (все те элементы, которые меньше чем средний элемент) можно рассматривать как левое поддерево, а правую (нижнюю) половину (все те элементы, которые больше чем средний элемент) можно рассматривать как правое поддерево.

Отсортированный массив может быть получен из дерева бинарного поиска при помощи прохождения этого дерева в симметричном порядке и вставки каждого элемента последовательно в некоторый массив по мере того, как он встречается в дереве. С другой стороны, для некоторого заданного отсортированного массива можно построить несколько соответствующих ему деревьев бинарного поиска. Рассматривая средний элемент массива как корень некоторого дерева и рассматривая рекурсивно оставшиеся элементы как левые и правые поддеревья, мы получим некоторое относительно сбалансированное дерево бинарного поиска (рис. 4.4). Рассматривая первый элемент массива в качестве корня дерева, а каждый последующий элемент как правого сына его предшественника, мы получим сильно разбалансированное дерево (рис. 4.5).

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

30

a1

47

a2

86

a3

95

a4

115

a5

130

a6

138

a7

159

a8

166

a9

184

a10

206

a11

212

a12

219

a13

224

a14

237

a15

258

a16

296

a17

307

a18

314

a19

Рис. 4.4

Рис. 4.5