КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
Включение и исключение в дереве
Begin Begin Begin Begin Else Begin Begin Type Бинарное дерево 9.4.1 Структура бинарного дерева Упорядоченные деревья второй степени (m -арные деревья при m =2) называют двоичными или бинарнымидеревьями. Упорядоченное бинарное дерево можно определить как множество вершин, которое либо пусто, либо состоит из корня с двумя отдельными двоичными деревьями, которые называют левым и правымподдеревьями этого корня. Деревья степени больше двух называют сильно ветвящимися деревьями (multiway trees). При представлении бинарного дерева в виде связного списка каждый элемент может содержать поля данных и два структурных указателя: указатель (Left) левого сына и указатель (Right) правого сына. Такое представление называется естественным представлением бинарного дерева. Тип бинарного дерева (базовый тип дерева) может быть объявлен следующим образом: Pvertex = ^Tvertex; Tvertex = Record Dat: <поля данных>; Left, Right: Pvertex; End; Var CurrentVertex, Root: Pvertex; CountVertex: Integer;
где Dat, как и ранее, - совокупность информационных полей; Left и Right поля структурных указателей. Поля данных мы будем использовать для размещения меток вершин. Переменные-указатели CurrentVertex и Root и необходимы для идентификации соответственно некоторой текущей вершины и корня. CountVertex - количество вершин в дереве. На рисунке 9.8 изображена структура естественного представления бинарного дерева (пустые поля указателей содержат пустые ссылки).
Рисунок 9.8 - Естественное представление бинарного дерева
9.4.2 Формирование бинарного дерева Предположим, что нужно построить такое бинарное дерево, которое при заданном количестве вершин N имела бы минимальную высоту. Очевидно, минимальная высота дерева достигается, если на всех уровнях, кроме последнего, поместить максимально возможное число вершин. Этого можно добиться, размещая «приходящие» в дерево вершины поровну слева и справа от той вершины, которая будет для них родителем. В результате при каждом увеличении количества вершин мы будем получать деревья, показанные на рисунке 9.9.
Рисунок 9.9 - Сбалансированные бинарные деревья для различных N
Дерево, имеющее структуру, показанную на рисунке 9.9, называется сбалансированным деревом (balanced tree, AVL-tree). В таком дереве число потомков в левом и правом поддереве любой вершины отличается не более, чем на 1. Алгоритм формирования сбалансированного бинарного дерева допускает следующую рекурсивную формулировку: - взять одну вершину в качестве корня; - построить тем же способом левое поддерево с Nleft = N Div 2 вершинами; - построить тем же способом правое поддерево с Nright = N - Nleft - 1 вершинами. Вышеприведенному алгоритму соответствует рекурсивная функция BinaryTreeCreate, приведенная ниже: Function BinaryTreeCreate(N: Integer): Pvertex; Var Nleft, Nright: Integer; If N = 0 Then Tree:= Nil Nleft:= N Div 2; Nright:= N - Nleft - 1; New(CurrentVertex); BinaryTreeCreate:= CurrentVertex; With CurrentVertex^ Do Begin <занесение данных в поля Dat> Left:= BinaryTreeCreate(Nleft); Right:= BinaryTreeCreate(Nright); End; End; End;
Для использования функции BinaryTreeCreate нужно передать ей значение числа вершин и выполнить вызов в следующей форме: Root:= BinaryTreeCreate(CountVertex);
9.4.3 Обход бинарного дерева Методы обхода дерева любой степени, рассматриваемые в подразделе 10.3, переформулируем в отношении бинарных деревьев. 1) Нисходящий обход: - обработка корня, - нисходящий обход левого поддерева, - нисходящий обход правого поддерева. Вершины дерева, изображенного на рисунке 9.8, поступали бы на обработку при обходе нисходящим методом в следующем порядке: a, b, d, h, i, e, c, f, g, j. 2) Смешанный обход: - смешанный обход левого поддерева, - обработка корня, - смешанный обход правого поддерева. Например, при обходе дерева на рисунке 9.8 смешанным методом вершины обрабатываются в следующей последовательности: h, d, i, b, e, a, f, c, j, g. 3) Восходящий обход: - восходящий обход левого поддерева, - восходящий обход правого поддерева, - обработка корня. Порядок обработки вершин того же дерева при восходящем обходе выглядит так: h, i, d, e, b, f, j, g, c, a. Для методов обхода в применении к бинарным деревьям часто применяют специфичные названия: нисходящий обход называют обходом pre‑order, смешанный обход - обходом in-order и восходящий - обходом post‑order. Обход post‑order чаще всего применяется для уничтожения всех вершин в бинарном дереве, когда процесс уничтожения можно было бы описать следующим образом: «чтобы уничтожить все вершины бинарного дерева, необходимо уничтожить левое поддерево корня, затем правое поддерево, а затем и сам корень». Все три метода легко представить рекурсивными процедурами. Прежде чем это сделать, необходимо определить процедуру, активируемую на этапе «обработка». Такая процедура должна выполнять некоторые действия над вершиной, к которой получен доступ на текущем шаге просмотра. А доступ к элементу связной структуры легче всего обеспечить через указатель, который назовем pNode. Текст такой процедуры может выглядеть, например, следующим образом: Procedure ProcessingNode(pNode: Pvertex); Var S: String; S:= <преобразование информационных Form1.Memo1.Lines.Append(S); End;
Теперь можно привести тексты трех подпрограмм обхода, которые реализуют приведенные выше рекурсивные алгоритмы: Procedure PreOrder(pRoot: Pvertex); If (aRoot <> Nil) Then Begin ProcessingNode(pRoot); PreOrder(pRoot^.Left); PreOrder(pRoot^.Right); End; End; Procedure InOrder(pRoot: Pvertex); If (aRoot <> Nil) Then Begin InOrder(pRoot^.Left); ProcessingNode(pRoot); InOrder(pRoot^.Right); End; End;
Procedure PostOrder(pRoot: Pvertex); If (aRoot <> Nil) Then Begin PostOrder(pRoot^.Left); PostOrder(pRoot^.Right); ProcessingNode(pRoot); End; End;
Для активации любой из этих трех процедур, следует воспользоваться вызовом в следующем виде: <имя процедуры>(Root); где Root - указатель корня, например: PostOrder(Root).
9.4.4 Преобразование любого дерева к бинарному дереву Любое m -арное дерево (т. е. дерево степени m) может быть преобразовано в эквивалентное ему бинарное дерево, которое проще исходного дерева с точки зрения представления в памяти и обработки. Графически такое преобразование сводится к следующим действиям: 1) сначала в каждом узле исходного дерева вычеркиваем все ветви, кроме самой левой ветви, которая соответствует ссылке на старшего сына; 2) в получившемся графе соединяем те узлы одного уровня, которые являются братьями в исходном дереве. На рисунке 9.10 приведен пример такого преобразования, причем после него из некоторых элементов, исходят две ссылки: горизонтальная соединяет данный элемент с его младшим (в исходном дереве) братом, а вертикальная - с его старшим сыном. Если на рисунке 9.10 повернуть все ссылки на 45° по часовой стрелке, то получим структуру, очень похожую на двоичное дерево. Однако считать ее таковым было бы ошибкой, поскольку функционально горизонтальные и вертикальные ссылки на рисунке 9.10 б имеют совершенно разный смысл. Правильнее было бы использовать следующую интерпретацию: после выполнения указанных преобразований из сыновей каждого родителя образуется линейный список, причем на старшего сына указывает ссылка от его родителя, а сам старший сын находится в голове списка своих братьев.
Рисунок 9.10 - Преобразование 3-арного дерева к бинарному
Пользуясь аналогичным алгоритмом можно представить в виде двоичного дерева и лес. На рисунке 9.11 показаны этапы преобразования леса из двух деревьев в бинарное дерево. Переход от m -арного дерева (или леса) к представлению в виде двоичного дерева при естественном связном хранении сокращает объем занимаемой памяти, поскольку каждый элемент m -арного дерева должен иметь m полей для логических указателей, тогда как элемент двоичного дерева имеет только два таких поля. С другой стороны, при таком преобразовании нужно помнить о функциональном назначении левой и правой ссылок и учитывать это при обработке дерева.
Рисунок 9.11 - Преобразование леса к бинарному дереву
Рассмотрим некоторые особенности операций включения и исключения в любом m ‑арном дереве. 9.5.1 Включение в дереве Включаемым в дерево объектом является некоторое (другое) дерево, которое затем станет поддеревом. При выполнении операции включения должны быть заданы: 1) включаемое поддерево (т. е. в памяти должна существовать соответствующая древовидная структура), 2) та вершина исходного дерева, к которой «подвешивается» в качестве ветви включаемое дерево и 3) индекс, назначаемый поддереву и определяющий старшинство его корня среди сыновей вершины подключения. В результате операции включения поддерева Y в вершину Х исходного дерева степень исхода вершины Х увеличивается на единицу и у этой вершины появляется еще один сын. При этом в общем случае потребуется заново перенумеровать вершины-сыновья узла X. 9.5.2 Исключение в дереве Исключаемым объектом, применительно к произвольному дереву, является некоторое поддерево. В операции исключения следует указать вершину исходного дерева, играющую роль корня исключаемого поддерева, и номер (или индекс) исключаемого поддерева, поскольку одна вершина в зависимости от ее степени исхода может играть роль корня для разных поддеревьев. Пусть Х - некоторая вершина произвольного дерева, а вершины, Y1..., Yn - ее сыновья. Тогда исключение i -ого поддерева вершины Х означает уменьшение степени исхода Х на единицу и удаление из исходного дерева ветви Х ® Y i , и поддерева, корнем которого служит вершина Y i. В результате такого удаления вершина Х может стать листом.
Дата добавления: 2017-02-01; Просмотров: 48; Нарушение авторских прав?; Мы поможем в написании вашей работы! |