2015-04-15 9 views
1

У меня проблема с этой домашней работой. Я должен написать код в прологе, который покажет мне самый глубокий путь к листу дерева.Путь в двоичном дереве - Пролог

Дерево представлено как:

tree([ [ [],r,[[],u,[[],t,[]]] ], a , [ [], c, [] ]]) 

Где [], как ноль и является корнем.

Он должен показать мне что-то вроде этого: PATH = [a, r, u, t]

я буду очень благодарен.

Решение:

deepest(T,D) :- aggregate(max(L,P),(path(T,P),length(P,L)),max(_,D)). 

path([],[]). 
path([L,K,R],[K|P]) :- path(L,P) ; path(R,P). 

Тест:

?- tree(T),deepest(T,P). 
T = [[[], r, [[], u, [[], t|...]]], a, [[], c, []]], 
P = [a, r, u, t]. 
+3

Что вы пробовали? – joel76

+0

Дерево выглядит так: [Дерево] (http://i.imgur.com/wcabf7V.png) @repeat – Bampelito

+0

'% Дерево Дерево ([[[], r, [[], u, [[] , t, []]]], a, [[], c, []]]). % Домашнее задание 1 % Интерфейс: most_dep_path (TREE, PATH): - % Пример тестирования: % tree (X), most_dep_path (X, PATH), print (X). % Ожидаемый результат: % X = [[[], r, [[], u, [[], t | ...]]], a, [[], c, []]], % PATH = [a, r, u, t]. Я извиняюсь за код. Это похоже на беспорядок. :/@repeat – Bampelito

ответ

1

Я знаю, мы не должны делать ТТВ ... но это решение - как это - вероятно, не будет adeguate для вашего класса. В любом случае, надеюсь, что это поможет вам справиться с такими проблемами в Prolog.

deepest(T,D) :- aggregate(max(L,P),(path(T,P),length(P,L)),max(_,D)). 

path([],[]). 
path([L,K,R],[K|P]) :- path(L,P) ; path(R,P). 

тест:

?- tree(T),deepest(T,P). 
T = [[[], r, [[], u, [[], t|...]]], a, [[], c, []]], 
P = [a, r, u, t]. 

Примечание: после того, как вы усвоили основные из этого языка, как правило, не требуется отладить. Решение достаточно декларативно ...

+0

Хорошее и простое решение. Я думал, что это будет немного сложнее написать. Спасибо. – Bampelito

1

Поскольку это домашнее задание, я не дам вам решение сразу.

Прежде всего, давайте посмотрим на вашу древовидную структуру. Когда вы смотрите на дерево, вы можете увидеть один из двух вариантов: либо это будет нуль, представленный как [], либо он будет узлом со значением и двумя поддеревьями [LeftSubTree, Value, RightSubTree]. Следовательно, ваш предикат должен иметь два положения для этих двух случаев.

В этих двух случаях, что является самым глубоким путем? Ну, для nil ответ прост: нет узлов, поэтому самый длинный путь на самом деле пустой список.

Для узла дерева, который не является нипом, каким будет самый длинный путь? Он начнется со значения в текущем узле и продолжит либо левое, либо правое поддерево, в зависимости от того, что глубже. Таким образом, чтобы получить самый глубокий путь от узла, вычислите самый глубокий путь рекурсивно в левом и правом поддереве, возьмите с них больше времени и значение plop из текущего узла спереди.

Чтобы реализовать это таким образом, вы обнаружите, что очень удобно иметь вспомогательный предикат longer(List1, List2, LongerList), который поместит больше из List1 и List2 в LongerList.

1

Вот чистый вариант, который не требует мета-предикатов всех решений, таких как aggregate/3.

Во-первых, вот ваш образец дерево снова:

sampleTree([[[],r,[[],u,[[],t,[]]]],a,[[],c,[]]]). 

Далее is_tree/1 определяет, какие деревья выглядят как:

is_tree([]). 
is_tree([Left,_,Right]) :- 
    is_tree(Left), 
    is_tree(Right). 

Наконец, определим tree_leftmostLongestPath/2, которые мы используем для pre-order tree traversal.

По сравнению с is_tree/1, tree_leftmostLongestPath_/4 имеет 3 дополнительных аргумента:

  • RPath что путь до сих пор в обратном порядок
  • Best0 пара Len-Path и имеет самый длинный путь найден до сих пор
  • Best также представляет собой пару Len-Path и содержит самый длинный путь всего дерева/поддерева

Вот код:

:- use_module(library(clpfd)). 

tree_leftmostLongestPath(Tree, Path) :- 
    tree_leftmostLongestPath_(Tree, [], 0-[], _-Path). 

% "internal" auxiliary predicate 
tree_leftmostLongestPath_([], RPath, Best0, Best) :- 
    Best0 = L0-_, 
    length(RPath, Len), 
    ( Len #=< L0,      Best = Best0 
    ; Len #> L0, reverse(RPath, Path), Best = Len-Path 
    ). 
tree_leftmostLongestPath_([Left,Name,Right], RPath, Best0, Best) :- 
    RPath1 = [Name|RPath], 
    tree_leftmostLongestPath_(Left , RPath1, Best0, Best1), 
    tree_leftmostLongestPath_(Right, RPath1, Best1, Best). 

Некоторые запросы и ответы:

?- sampleTree(Tree), tree_leftmostLongestPath(Tree, Path). 
Path = [a,r,u,t], Tree = [[[],r,[[],u,[[],t,[]]]],a,[[],c,[]]]). 

?- is_tree(Tree), tree_leftmostLongestPath(Tree, Path). 
    Path = []  , Tree = [] 
; Path = [A] , Tree = [[],A,[]] 
; Path = [A,B] , Tree = [[],A,[[],B,[]]] 
; Path = [A,B,C], Tree = [[],A,[[],B,[[],C,[]]]] 
… 
+0

Интересно, что вы подразумеваете под «чистым» в своем первом предложении. Не могли бы вы объяснить? – migfilg

+0

Теперь я понимаю, что вы имеете в виду, спасибо. Но обратите внимание, что «чистый» в этом контексте, скорее всего, будет восприниматься как «чистый Пролог», и это не то, что вы имеете в виду, и может привести к путанице. Позвольте мне добавить, что ваш смысл «чистого» является слишком общим: если можно скрыть разрезы и другие подобные побочные эффекты в предикатах, которые «ведут себя так, как будто они чисты», тогда все предикаты, кроме верхнего уровня, могут быть нечистыми в вашем смысле. – migfilg

+0

Я понимаю, что вы имеете в виду, но я не вижу смысла иметь код, внешне внешне чистый, как в (2), если он не написан для представления его людям, а именно, когда их знание Пролога мало. Или, может быть, когда он написан только в ответ на вызов ... – migfilg

Смежные вопросы