Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Conspekt.doc
Скачиваний:
11
Добавлен:
31.08.2019
Размер:
1.39 Mб
Скачать

5.18.2 Преобразование списка в упорядоченное дерево

list_tree(S,T)

Если S = nil, то Т=[]

S = [ H|T ],то добавить голову списка H к дереву, которое получится путем преобразования хвоста списка Т в дерево.

list_tree([],nil).

list_tree([ H|T ],Tree):-

list_tree(T,Tree1),

add(Tree1, H, Tree).

5.18.3 Преобразование дерева в список

tree_list(T,S)

1). T=nil, S=[]

2). T= tree(Лд, К, Пд), преобразовать Лд в список SL,

преобразовать Пд в список SR, соединить списки S1, корень,

S2 (в указанной последовательности) в список S.

tree_list(nil,[]).

tree_list( tree(L,K,R),S) :-

tree_list(L,SL), tree_list(R,SR),

append( SL, [ X|SR ], S ).

ВИДЫ ОПЕРАЦИЙ НАД ДЕРЕВЬЯМИ

1). Обход дерева.

2). Добавление узла в дерево.

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

1). Обход дерева включает в себя следующие процедуры:

а) обработка корня дерева;

б) обход левого поддерева(Лд);

в) обход правого поддерева(Пд);

Виды обходов:

сверху-вниз <==> а - б - в

слева-направо <==> б - а - в

снизу-вверх <==> б - в - а

Если операции обхода дерева выполняются в порядке б - в - а

a

--------+-------¬

b f

---------+-------¬

c d

-------+------¬ ------+-------¬

nil nil nil e

---------+--------¬

nil nil

Видно, что в узел м. зайти 3 раза.

Если корень дерева обрабатывается при первом заходе, то это обход сверху-вниз.

Если мы обрабатываем корень при втором заходе, то это обход слева-направо.

Если мы обрабатываем корень при третьем заходе, то это обход снизу-вверх.

5.18.4 Удаление элемента из дерева

Удаление листа дерева - простая процедура, однако, удале-

ние произвольного элемента из дерева может быть сопряжено с

удалением целого поддерева, связанного с этим узлом.

Удалить лист из дерева м. с помощью процедуры add().

del_list(T1,X,T2) :- add(T2,X,T1).

Рассмотрим дерево

Удалить X - получится "дыра":

Если одно из поддеревьев L1 или R1 пустое, то мы просто- должны оставшееся дерево прикрепить к узлу:

Если оба поддерева непусты, то поступают с.о:

1).Находят в правом поддереве самую левую вершину. Она

самая минимальная поэтому, чтобы не нарушать упорядоченность

дерева, ее перемещают на место узла.

2).Находят в левом поддереве самую правую вершину. Она

самая максимальная поэтому, чтобы не нарушать упорядоченность

дерева, ее перемещают на место узла.

% удалить(Т,X,T1).

delete( tree(nil,X,R), X, R).

delete( tree(L,X,nil), X, L).

delete( tree(L,X,R), X, tree(L,Y,R1) ):-

del_min(R,Y,R1).

delete( tree(L,K,R), X, tree(L1,K,R) ):-

more(K,X), delete(L,X,L1).

delete( tree(L,K,R), X, tree(L,K,R1) ):-

more(X,K), delete(R,X,R1).

del_min( tree(nil,X,R), X, R).

del_min( tree(L,K,R), X, tree(L1,K,R):-

del_min(L,K,L1).

Другой способ организации отношения delete() - изменение отношения add().

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

add() ::-

1) Добавить X на место корня

или

2) Если X>Корень, то добавить X в Пд

X<Корень, -- // -- в Лд

Чтобы реализовать 1-ое условие необходимо определить о ношение add_kor(D,X,D1) ( добавить корень X к дереву D с получением дерева D1).

1)X < Y

2)X > Y

При построении L1 и L2 должны выполняться условия:

1) L1 и L2 - бинарные деревья

2) Элементы L1 и L2 соответствуют элементам L

3) L1 < X < L2

R1 > X > R2

Эти 3 условия могут быть описаны с.о:

add_kor(L,X, tree(L1,X,L2)) и add_kor(R,X, tree(R1,X,R2))

Итак, определим предикат добавления:

add(D,X,D1):- add_kor(D,X,D1).

add( tree(L,K,R), X, tree(L1,K,R)):-

more(K,X), add(L,X,L1).

add( tree(L,K,R), X, tree(L,K,R1)):-

more(X,K), add(R,X,R1).

add_kor(nil,X, tree(nil,X,nil)).

add_kor( tree(L,Y,R), X, tree(L1,X, tree(L2,Y,R)) ):-

more(Y,X), add_kor(L, X, tree(L1,X,L2)).

add_kor( tree(L,Y,R), X, tree( tree(L,Y,R1),X,R2)) ):-

more(X,Y), add_kor(R, X, tree(R1,X,R2)).

В эту процедуру не заложено никаких ограничений на уро-

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

направлении:

?- add(D,5,D1), 1). 5 2). 8

add(D1,8,D2), / \ / \

add(D2,4,D3), nil nil 5 nil

add(DN,8,D3). / \

nil nil

3). 8 4). 5

/ \ / \

5 nil 4 nil

/ \ / \

4 nil nil nil

/ \

nil nil

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

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