Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шпора - переписать.docx
Скачиваний:
10
Добавлен:
24.09.2019
Размер:
82 Кб
Скачать
☆

Часть V : avl – Деревья

Бинарное дерево является сбалансированным, если для любого узла дерева высоты его левого и правого поддеревьев отличаются не более чем на 1

-1, левое поддерево выше на 1

balance = 0, высота поддеревьев одинаковая

+1, правое поддерево выше на 1

Node (balance,key,left,right,parent) or {balance -> int hleft; int hright;}

  • Вставить новый элемент как в двоичное дерево поиска

  • Скорректировать свойство сбалансированности узлов дерева

  • При необходимости скорректировать само AVL-дерево

Коррекция узлов

x – новый узел дерева

q = x

p = q->parent – родительский узел

while p ≠ EList и p->balance = 0 {

if q в левом поддереве p

p->balance = -1

else

p->balance = +1

q = p

p = q->parent

}

p – узел дерева, у которого p->balance ≠ 0, или EList

if p = EList

успех

if x в левом поддереве p и p->balance = +1 или x в правом поддереве p и p->balance = -1 {

p->balance = 0

успех

}

  • Удалить элемент так же, как в двоичном дереве поиска (с учетом внешних листьев – EList)

  • Скорректировать свойство сбалансированности узлов дерева

  • При необходимости скорректировать само AVL-дерево

Удалить узел из бинарного дерева поиска

x – дочерний узел удаленного элемента

p = x->parent

while p ≠ EList {

коррекция узла дерева p:

if x в левом поддереве p

p->hleft = p->hleft – 1

else

p->hright = p->hright – 1

dh = | p->hleft – p->hright |

if dh > 1{

коррекция дерева

успех

}

else

if dh = 1

успех

else

x = p

p = x->parent

} -- цикл while

p – узел AVL-дерева, для которого нарушены требования сбалансированности

insert()

{

p =root

if(p==NULL) p = new;

else if ( key<p->key)

{

insert(p->left);

if((p->left->h) – (p->right->h) == 2){

if(key < p->left->key){rotate_r(p)}

else {rotate_r(p->left); rotate_l(p);

}

}

else

{

insert(p->right);

if((p->right->h) – (p->left->h) == 2){

if(key < p->left->key){rotate_r(p)}

else {rotate_r(p->left); rotate_l(p);

}

}

}

Часть VI : b – Деревья

В-дерево степени t:

  • Каждый узел, кроме корня и листьев, имеет минимум t, максимум 2t дочерних узлов

  • Каждый узел, кроме корня, содержит минимум t – 1, максимум 2t – 1 ключей; узел заполнен, если он имеет ровно 2t – 1 ключей

  • Корень имеет минимум 1 ключ и два дочерних узла

  • Все листья расположены на одной и той же глубине, которая равна высоте дерева h

Поиск в В-дереве

Если ключ содержится в корне, он найден. Иначе определяем интервал и идём к соответствующему сыну. Повторяем, пока не дошли до листа.

Вставка в В-дерево

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

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

  1. Если х - не лист,

    1. Определяем интервал, где должен находиться K. Пусть y - соответствующий сын.

    2. Рекурсивно добавляем K к дереву потомков y.

    3. Если узел y полон, то есть содержит   ключей, расщепляем его на два. Узел   получает первые   из ключей y и первые   его потомков, а узел   - последние   из ключей y и последние   его потомков. Медианный из ключей узла y попадает в узел х, а указатель на y в узле x заменяется указателями на узлы   и  .

  2. Если x - лист, просто добавляем туда ключ K.

Теперь определим добавление ключа K ко всему дереву. Буквой R обозначается корневой узел.

  1. Добавим K к дереву потомков R.

  2. Если R содержит теперь   ключей, расщепляем его на два. Узел   получает первые   из ключей R и первые   его потомков, а узел  - последние   из ключей R и последние   его потомков. Медианный из ключей узла R попадает вo вновь созданный узел, который становится корневым. Узлы   и   становятся его потомками.

Удаление элемента

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

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

Если   - не лист, а K - его  -й ключ, удаляем самый правый ключ из поддерева потомков  -го сына  , или, наоборот, самый левый ключ из поддерева потомков  -го сына  . После этого заменяем ключ K удалённым ключом. Удаление ключа происходит так, как описано в предыдущем абзаце.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]