Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Поиск со вставкой (с включением)




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

Для включения новой записи в дерево, прежде всего нужно найти тот узел, к которому можно присоединить новый элемент. Алгоритм поиска нужного узла тот же самый, что и при поиске узла с заданным ключом. Однако непосредственно использовать процедуру поиска нельзя, потому что по ее окончании не фиксирует тот узел, из которого была выбрана ссылка NIL (search = nil).

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

Псевдокод: P = tree Q = nil Whlie p <> nil do q = p if key = k(p) then search = p return endif if key < k(p) then p = left(p) else p = right(p) endif endwhile v = maketree(key, rec) if q = nil then tree = v else if key < k(q) then left(q) = v else right(q) = v endif endif search = v return Паскаль: p:= tree; q:= nil; whlie p <> nil do begin q:= p; if key = p^.k then begin search:= p; exit; end; if key < p^.k then p:= p^.left else p:= p^.right; end; v:= maketree(key, rec) if q=nil then tree:=v else if key < q^.k then q^.left:= v else q^.right:= v; search:= v;

Поиск с удалением

Удаление узла не должно нарушить упорядоченности дерева. Возможны три варианта:

1) Найденный узел является листом. Тогда он просто удаляется и все.

2) Найденный узел имеет только одного сына. Тогда сын перемещается на место отца.

3) У удаляемого узла два сына. В этом случае нужно найти подходящее звено поддерева, которое можно было бы вставить на место удаляемого. Такое звено всегда существует:

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

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

Предшественником удаляемого узла называют самый правый узел левого поддерева (для 12 - 11). Преемником - самый левый узел правого поддерева (для 12 - 13).

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

p - рабочий указатель;

q - отстает от р на один шаг;

v - указывает на приемника удаляемого узла;

t - отстает от v на один шаг;

s - на один шаг впереди v (указывает на левого сына или пустое место).

На узел 13 в конечном итоге должен указывать v, а указатель s - на пустое место (как показано на рис. 5.9).

Псевдокод: q = nil p = tree while (p <> nil) and (k(p) <> key) do q = p if key < k(p) then p = left(p) else p = right(p) endif endwhile if p = nil then ‘Ключ не найден’ return endif if left(p) = nil then v = right(p) else if right(p) = nil then v = left(p) else ‘У nod(p) - два сына’ ‘Введем два указателя (t отстает от v на 1 ‘шаг, s - опережает) t = p v = right(p) s = left(v) while s <> nil do t = v v = s s = left(v) endwhile if t <> p then ‘v не является сыном p’ left(t) = right(v) right(v) = right(p) endif left(v) = left(p) endif endif if q = nil then ‘p - корень’ tree = v else if p = left(q) then left(q) = v else right(q) = v endif endif freenode(p) return   Паскаль: q:= nil; p:= tree; while (p <> nil) and (p^.k <> key) do begin q:= p; if key < p^.k then p:= p^.left else p:= p^.right; end; if p = nil then WriteLn(‘Ключ не найден’); exit; end; if p^.left = nil then v:= p^.right else if p^.right = nil then v:= p^.left else begin {Введем два указателя (t отстает от v на 1 шаг, s - опережает)} t:= p; v:= p^.right; s:= v^.left; while s <> nil do begin t:= v; v:= s; s:= v^.left; end; if t <> p then begin WriteLn(‘v не является сыном p’); t^.left:= v^.right; v^.right:= p^.right; end; v^.left:= p^.left; end; end; if p = q^.left then q^.left:= v else q^.right:= v; end; dispose(p); end;

Контрольные вопросы

1. В чем состоит назначение поиска?

2. Что такое уникальный ключ?

3. Какая операция производится в случае отсутствия заданного ключа в списке?

4. В чем разница между последовательным и индексно-последовательным поиском?

5. Какой из них более эффективный и почему?

6. Какие способы переупорядочивания таблицы вы знаете?

7. Основные отличия метода перестановки в начало от метода транспозиции.

8. Где они будут работать быстрее, в массиве или списке?

9. В каких списках они работают, упорядоченных или нет?

10. В чем суть бинарного поиска?

11. Как можно обойти бинарное дерево?

12. Можно ли применять бинарный поиск к массивам?

13. Если удалить корень в непустом бинарном дереве, какой элемент станет на его место?





Поделиться с друзьями:


Дата добавления: 2016-03-28; Мы поможем в написании ваших работ!; просмотров: 866 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Велико ли, мало ли дело, его надо делать. © Неизвестно
==> читать все изречения...

2524 - | 2183 -


© 2015-2025 lektsii.org - Контакты - Последнее добавление

Ген: 0.013 с.