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

Представление двоичных деревьев

Бинарное дерево можно представить в виде динамической структуры данных, состоящей из узлов, каждый из которых содержит кроме данных не более двух ссылок на правое и левое бинарное дерево. На каждый узел имеется одна ссылка. Начальный узел называется корнем.

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

Пример фрагмента программы дерева

Type    Tree=^s;    S=record    Inf: <тип хранимой информации>;    Left , right : tree ; End ;

Пример дерева, организованного в виде динамической структуры данных:

рис.1

Дерево поиска

Данное дерево (рис.1) организовано таким образом, что для каждого узла все ключи (значения узлов) его левого поддерева меньше ключа этого узла, а все ключи его правого поддерева больше. Такой способ построения дерева называется деревом поиска или двоичным упорядоченным деревом.

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

Поиск в упорядоченном дереве выполняется по следующему рекурсивному алгоритму:

Если дерево не пусто, то нужно сравнить искомый ключ с ключом в корне дерева:

- если ключи совпадают, поиск завершен;

- если ключ в корне больше искомого, выполнить поиск в левом поддереве;

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

Если дерево пусто, то искомый элемент не найден.

Дерево поиска может быть использовано для построения упорядоченной последовательности ключей узлов. Например, если мы используем симметричный порядок обхода такого дерева, то получим упорядоченную по возрастанию последовательность: 1 6 8 10 20 21 25 30.

Можно организовать «зеркально симметричный» обход, начиная с правого поддерева, тогда получим упорядоченную по убыванию последовательность: 30 25 20 10 8 6 1.

Таким образом, деревья поиска можно применять для сортировки значений.

Операции с двоичными деревьями

Для работы с двоичными деревьями важно уметь выполнять следующие операции:

  • Поиск по дереву;

  • Обход дерева;

  • Включение узла в дерево;

  • Удаление узла из дерева.

Алгоритм поиска по дереву мы рассмотрели выше.

Функция поиска :

function find(root:tree; key:integer; var p, parent:tree):Boolean; begin    p:=root;    while p<>nil do begin       if key=p^.inf then begin{ узел с таким ключом есть }          find:=true;          exit;       end;       parent:=p {запомнить указатель на предка}       if key<p^.inf then          p := p ^. left {спуститься влево}       else p := p ^. right ; {спуститься вправо}    end; find:=false; end;

Наибольший интерес для двоичного дерева поиска представляет симметричный обход, т.к. он дает нам упорядоченную последовательность ключей.

Реализуем обход дерева в виде рекурсивной процедуры.

Пример обхода дерева с помощью рекурсии

Procedure obhod(p:tree); Begin    if p<>nil then    begin       obhod(p^.left);       writeln(p^.inf);       obhod(p^.right);    end; end;

Вставка узла в двоичное дерево поиска

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

Например, необходимо вставить в дерево, изображенное на рисунке, узел с ключом 5.

Сравниваем 5 с ключом корня; 5<10, следовательно, уходим в левое поддерево. Сравниваем 5 и 6; 5<6, спускаемся влево. Следующий узел является конечным (листом). Сравниваем 5 и 1; 5>1, следовательно, вставляем правого сына. Получим дерево с новым узлом, которое сохранило все свойства дерева поиска.

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

Сложнее всего случай, когда у удаляемого узла есть оба потомка.

Есть простой особый случай: если у правого потомка удаляемого узла нет левого потомка, удаляемый узел заменяется на своего правого потомка, а его левый потомок подключается вместо отсутствующего левого потомка к замещающему узлу.

В общем же случае на место удаляемого узла ставится самый левый лист его правого поддерева (или наоборот – самый правый лист его левого поддерева). Это не нарушает свойств дерева поиска.

Корень дерева удаляется по общему правилу за исключением того, что заменяющий его узел не требуется присоединять к узлу-родителю.

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