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

13.3. Добавление и удаление элемента

Эти операции меняют дерево, сохраняя свойство упорядоченности. Как увидим, добавление сравнительно просто, а удаление чуть сложнее.

Добавление

Процедура tree-insert добавляет заданный элемент в подходящее меcто дерева Т (сохраняя свойство упорядоченности). Параметром процедуры является указатель z на новую вершину, в которую помещены значения key[z] (добавляемое значение ключа), left[z] =nil и right[z] = NIL. В ходе работы процедуры меняет дерево Т и (возможно) некоторые поля вершины 2, после чего новая вершина с данным значением ключа оказывается вставленной в подходя место дерева.

tree-!nsert(t\ z)

  1. у <- nil

  2. х <-root[Т]

  3. while х<> nil

4 do у «— х

5 if key[z] < key[x]

  1. then x «— left[x]

  2. else x «— right[x]

  1. p[z] <- у

  2. if у = nil

  1. then root[T] <- z

  2. else if key[z] < key[y]

  1. then left[y] <- z

  2. else right[y] <— z

На рис. 13.3 показано, как работает процедура TREE-INSERT. Подобно процедурам tree-search и iterative-tree-search, она двигается вниз по дереву, начав с его корня. При этом в вершине у сохраняется указатель на родителе вершины х (цикл в строках 3-7). Сравнивая key[z] с key[x], процедура решает, куда идти — налево или направо. Процесс завершается, когда х становится равным nil. Этот nil стоит как раз там, куда надо поместить z, что и делается в строках 8-13. Как и остальные операции, добавление требует времени O(h) для дер высоты h

Рис. 13.3. Добавление элемента с ключом 13. Светло-серые вершины находятся на пу­ти от корня до позиции нового элемента. Пунктир связывает новый элемент со старыми.

Удаление

Параметром процедуры удаления является указатель на удаляемую вершину. При удалении возможны три случая, показанные на рис. 13.4. Если у z нет детей, для удаления z достаточно поместить nil в соответствующее поле его родителя (вместо z). Если у z есть один ребёнок, можно «вырезать» z, соединив его родителя напрямую с его ребёнком. Если же детей двое, требуются некоторые приготовления: мы находим следующий (в смысле порядка на ключах) за z элемент у; у него нет левого ребёнка. Теперь можно скопировать ключ и дополнительные данные из вершины у в вершину z , а саму вершину у удалить описанным выше способом.

Примерно так и действует процедура TREE-DELETE (хотя рассматривает эти три случая в несколько другом порядке).

tree-delete(t, z}

1 if left[z]= NIL или right[z] = NIL

  1. then у <- z

  2. else у <- tree-successor(z)

4 if left[y] <> nil

5 then x <- left[y]

6 else x <- right[y]

7 if x <> nil

8 then p[x] <- p[y]

9 if p[y] = nil

  1. then root[T] <- x

  2. else if у = left[p[y]]

  1. then left[p[y]] <-x

  2. else right[p[y]] <- x

14 if у <> z

15 then key[z] <- key[y]

16 t> Копируем дополнительные данные, связанные с у.

17 return у

Рис. 13.4. Удаление вершины z из двоичного дерева поиска (а). Если вершина z не имеет

детей, её можно удалить без проблем (б). Если вершина r имеет одного ребёнка, помещаем её на место вершины z (в). Если у вершины z двое детей, мы сводим дело к предыдущему случаю, удаляя вместо неё вершину у с непосредственно следующим значением ключа (у этой вершины ребёнок один) и помещая ключ key[y] (и связанные с ним дополнительные данные) на место вершины z.

В строках 1-3 определяется вершина у, которую мы потом вырежем из дерева. Это либо сама вершина z (если у r не более одного ребёнка), либо следующий за z элемент (если у z двое детей). Затем в строках 4-6 переменная х становится указателем на существующего ребёнка вершины у, или равной NIL, если у у нет детей. Вершина у вырезается из дерева в строках 7-13 (меняются указатели в вершинах р[у] и х). При этом отдельно рассматриваются граничные случаи когда х = NIL или когда у является корнем дерева. Наконец, в строках 14-16, если вырезанная вершина у отлична от z, ключ (и дополнительные данные) вершины у перемещаются в z (ведь нам надо было удалить z, а не у). Haконец, процедура возвращает указатель у (это позволит вызывающей процедуре впоследствии освободить память, занятую вершиной у). Время выполнения есть O(h) на дереве высоты h.

Итак, мы доказали следующую теорему.

Теорема 13.2. Операции insert и delete могут быть выполнены за вре­мя O(h), где h высота дерева.