Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Data Structures and Algorithms in C++ 2e (На ру...docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.37 Mб
Скачать

428 Глава 10. Деревья поиска

10.1.2 Операции по обновлению

Деревья двоичного поиска позволяют внедрения вставки и стирают операционное использование

алгоритмы, которые являются довольно прямыми, но не тривиальными.

Вставка

Давайте предположим, что надлежащее двоичное дерево T поддерживает следующую операцию по обновлению:

insertAtExternal (v, e): Вставьте элемент e во внешнем узле v и расширьтесь

v, чтобы быть внутренним, имея новый (пустой) внешний узел chil-dren; ошибка происходит, если v - внутренний узел.

Учитывая эту функцию, мы выполняем вставку (k, x) для словаря, осуществленного с деревом двоичного поиска T, называя TreeInsert (k, x, T.root ()), который дан в Кодовом Фрагменте 10.2. Алгоритм TreeInsert (k, x, v):

Вход: ключ поиска k, связанная стоимость, x, и узел v Продукции T: новый узел w в поддереве T (v), который хранит вход (k, x)

w ¬ TreeSearch(k, v)

если T.isInternal (w) тогда

возвратите TreeInsert (k, x, T.left (w))идущий вправо было бы правильно также

T. insertAtExternal (w, (k, x)) Это - соответствующее место, чтобы поместить (k, x)

возвратите w

Кодовый Фрагмент 10.2: Рекурсивный алгоритм для вставки в дереве двоичного поиска.

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

Рисунок 10.4: Вставка входа с ключевыми 78 в дерево поиска рисунка 10.1: (a) нахождение, что положение вставляет; (b) получающееся дерево.

10.1. Деревья двоичного поиска 429

Удаление

Внедрение стирания (k) операция на карте M, осуществленной с деревом двоичного поиска T, немного более сложно, так как мы не хотим создавать любые «отверстия» в дереве T. Мы предполагаем, в этом случае, что надлежащее двоичное дерево поддерживает следующую дополнительную операцию по обновлению:

removeAboveExternal (v): Удалите внешний узел v и его родителя, заменив v's

родитель с родным братом v; ошибка происходит, если v не внешний.

Учитывая эту операцию, мы начинаем, наше внедрение операции стирают (k) карты ADT, называя TreeSearch (k, T.root ()) на T, чтобы счесть узел T хранением входа с ключом равный k. Если TreeSearch возвращает внешний узел, то нет никакого входа с ключом k в карте M, и состояние ошибки сообщено. Если, вместо этого, TreeSearch возвращает внутренний узел w, то w хранит вход, который мы хотим удалить, и мы отличаем два случая:

• Если один из детей узла w является внешним узлом, скажите узел z, мы просто пере -

переместите w и z от T посредством операции removeAboveExternal (z) на T.

Эта операция реструктурирует T, заменяя w с родным братом z, удаляя и w и z от T. (См. рисунок 10.5.)

• Если оба ребенка узла w являются внутренними узлами, мы не можем просто удалить

узел w от T, так как это создало бы «отверстие» в T. Вместо этого мы продолжаем двигаться как

следует (см. рисунок 10.6):

◦ Мы находим первый внутренний узел y, который следует за w в inorder пересечении

из T. Узел y является крайним левым внутренним узлом в правильном поддереве w,

и найден, идя сначала к правильному ребенку w и затем вниз T оттуда, после покинутых детей. Кроме того, покинутый ребенок x y является внешним узлом, который немедленно следует за узлом w в inorder пересечении T.

◦ Мы перемещаем вход y в w. Это действие имеет эффект удаления

прежний вход сохранен в w.

◦ Мы удаляем узлы x и y от T, звоня removeAboveExternal (x)

на T. Это действие заменяет y родным братом x и удаляет и x и y

от T.

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

Основанный на положении вариант удаления - то же самое, за исключением того, что мы можем пропустить начальный шаг призыва TreeSearch (k, T.root ()), чтобы определить местонахождение узла, содержащего ключ.