280 likes | 502 Views
доц. Светла Бойчева Факултет по математика и информатика СУ “Св. Климент Охридски”. Програмиране на Пролог. Дървета. Дърво – ацикличен свързан граф Двоични дървета Двоично - наредени дървета Балансирани дървета. Представяне на дърво. nil bintree(nil,R,nil)
E N D
доц. Светла Бойчева Факултет по математика и информатика СУ “Св. Климент Охридски” Програмиране на Пролог
Дървета • Дърво – ацикличен свързан граф • Двоични дървета • Двоично - наредени дървета • Балансирани дървета
Представяне на дърво nil bintree(nil,R,nil) bintree(LeftTree,Root,RigthTree)
Основни операции • Проверка дали дадено двоично дърво T е празно • Проверка дали даден елемент X принадлежи на дадено двоично дърво T • Проверка дали даден елемент X стои в листо дадено двоично дърво T • Oтпечатване на елементите, които стоят във възлите на дадено двоично дърво T • Образуване на списък от елементите, които стоят във възлите на дадено двоично дърво T • Образуване на списък от елементите, които стоят в листата на дадено двоично дърво T
member_tree(X,bintree(LeftTree,R,RightTree)):- ( X=R ; member_tree(X,LeftTree) ; member_tree(X,RightTree)). leaf(X, bintree(nil,X,nil)). leaf(X,bintree(LeftTree,Root,RightTree)):- leaf(X,LeftTree) ; leaf(X, RightTree). empty_tree(nil). % Селектори root(bintree(_,Root,_),Root). left_tree(bintree(LT,_,_),LT). right_tree(bintree(_,_,RT),RT).
member_tree(X,T):- ( root(T,R),X=R ; left_tree(T,LT),member_tree(X,LT) ; right_tree(T,RT), member_tree(X,RT)). leaf(X,T):- left_tree(T,LT),empty_tree(LT), right_tree(T,RT),empty_tree(RT), root(T,R),X=R. leaf(X,T):- ( left_tree(T,LT), leaf(X,LT) ; right_tree(T,RT), leaf(X, RT) ) .
tree2list(nil,[ ]). tree2list(T, List):- left_tree(T,LT), tree2list(LT, L1), root(T,R), right_tree(T,RT), tree2list(RT,L2), append(L1, [R|L2] ,List).
leaves2list(nil,[ ]). leaves2list(T, [R] ):-leaf(T),root(T,R). leaves2list(T, List):- left_tree(T,LT), leaves2list(LT, L1), right_tree(T,RT), leaves2list(RT,L2), append(L1,L2 ,List).
depth_tree(T,0):-empty_tree(T),!. depth_tree(T,D):- left_tree(T,LT),depth_tree(LT, N1), right_tree(T,RT),depth_tree(RT,N2), ( N1 < N2, !, D is N2+1 ; D is N1+1).
Задача • Предикат, който прави проверка дали даден връх X е родител (пряк) на друг даден връх Y в дадено дърво T. parent(X,Y,T):- root(T,X), (left_tree(T,LT), root(LT,Y) ; right_tree(T,RT), root(RT,Y) ). parent(X,Y,T):- ( left_tree(T,LT), parent(X,Y,LT) ; right_tree(T,RT), parent(X,Y,RT) ).
Задача • Предикат, който намира всички преки наследници на даден връх X в дадено дърво T. get_root(T,[R]):-root(T,R),!. get_root(T,[ ]). children(X,T,C):- root(T,X), left_tree(T,LT), get_root(LT, RL), right_tree(T,RT), get_root(RT, RR), append(RL,RR,C). children(X,T,C):- ( left_tree(T,LT), children(X, LT,C) ; right_tree(T,RT), children(X, RT,C)).
Основни операции • Да се напише предикат, който да намира път от X до Y за два дадени възела X и Y на дадено дърво T. way(X,Y,T,P):- children(X,T,C), ( member(Y,C), !, P=[X,Y] ; member(Z,C), way(Z,Y,T,Temp), P=[X|Temp]).
% Вариант 1 tree( t( t( t( t(nil,7,nil), 4, t(nil,2,nil)), 3 , nil ) , 5 , t(nil, 9 , t( t(nil,8,nil), 1, t(nil,6,nil)) ) ) ). % Селектори root(t(_,Root,_),Root). left_tree(t(LT,_,_),LT). right_tree(t(_,_,RT),RT). ?-tree(T),way(5,2,T).
% Вариант 2 tree( [ [ [ [nil,7,nil], 4, [nil,2,nil]], 3 , nil ] , 5 , [nil, 9 , [ [nil,8,nil], 1, [nil,6,nil]]]] ). % Селектори root([_,Root,_],Root). left_tree([LT,_,_],LT). right_tree([_,_,RT],RT). ?-tree(T),way(5,2,T).
Задача • Да се напише предикат, който да намира всички пътища от корен на дървото Т до негово листо. path(T, [ ] ):- empty_tree(T). path(T, [ R ] ):- root(T,R), left_tree(T,LT),empty_tree(LT), right_tree(T,RT),empty_tree(RT). path(T, [ R |Temp ] ):- root(T,R), left_tree(T,LT), path(LT,Temp). path(T, [ R |Temp ] ):- root(T,R), right_tree(T,RT), path(RT,Temp).
Основни операции • Проверка за два дадени възела X и Y на дадено дърво T дали има път от X до Y. • Намиране на дълбочината на дърво
Основни операции • Намиране на най-дългата дума, която може да бъде образуваня при последователно обхождане от корен към листо на възлите на двоично дърво с букви във възлите.
Намиране на най-голямото число, което може да бъде образувано при последователно обхождане от корен към листо на възлите на двоично дърво с цифри във възлите. max_num(T,Num):- findall(N, (path(T,P),list2number(P,N)), L), sort(L,S), reverse(S,[Num|_]).
% [1,2,3,4] -> 1234 list2number([],0). list2number(L,N):- append(Prev, [Last], L), list2number(Prev,Temp), N is Temp*10+Last.
% Втори начин max_num(T,X,1):-root(T,X), left_tree(T,LT),empty_tree(LT), right_tree(T,RT),empty_tree(RT),!. max_num(T,N,K1):-root(T,X), left_tree(T,LT),empty_tree(LT), right_tree(T,RT),max_num(RT,M,K), N is M + X*10**K, K1 is K+1.
max_num(T,N,K1):-root(T,X), right_tree(T,RT),empty_tree(RT),!, left_tree(T,LT),max_num(LT,M,K), N is M + X*10**K, K1 is K+1. max_num(T,N,K1):-root(T,X), left_tree(T,LT),max_num(LT,M,K), right_tree(T,RT),max_num(RT,U,W), (M>U,!, N is M + X*10**K, K1 is K+1 ; N is U + X*10**W, K1 is W+1).
Намиране на най-дългата дума, която може да бъде образуваня при последователно обхождане от корен към листо на възлите на двоично дърво с букви във възлите.
Проверка дали дадено дърво е балансирано balanced_tree(T):-empty_tree(T). balanced_tree(T):- left_tree(T,LT), depth_tree(LT,K), right_tree(T,RT), depth_tree(RT,M), abs(K-M) =< 1.
Основни операции • Проверка дали дадено дърво е идеално балансирано perfect_tree(T):-empty_tree(T). perfect_tree(T):- left_tree(T,LT), depth_tree(LT,K), right_tree(T,RT), depth_tree(RT,M), abs(K-M) =< 1, perfect_tree(LT), perfect_tree(RT).
Основни операции • Построяване на двоично наредено дърво по зададен списък от числа gen_tree(List,OldTree,NewTree) gen_tree([ ],T,T). gen_tree([X|L],nil,NewTree):- gen_tree(L, t(nil,X,nil), NewTree). gen_tree([X|L],T,NewTree):- root(T,R), left_tree(T,LT), right_tree(T,RT), ( X < R, !, insert(X,LT, NewLT), gen_tree(L, t(NewLT,R,RT), NewTree) ; insert(X,RT,NewRT), gen_tree(L, t(LT,R,NewRT), NewTree) ).
Основни операции insert(X,nil,t(nil,X,nil)). insert(X,T, Result):- root(T,R), left_tree(T,LT), right_tree(T,RT), (X>R,!, insert(X,RT,NewRT), Result= t(LT,R,NewRT) ; insert(X,LT,NewLT), Result= t(NewLT,R,RT) ).
Основни операции • Сортиране чрез двоично наредено дърво tree_sort(L,Result):- gen_tree(L,nil,Tree), tree2list(Tree,Result).