Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Prolog中将树转换为列表?_Prolog - Fatal编程技术网

如何在Prolog中将树转换为列表?

如何在Prolog中将树转换为列表?,prolog,Prolog,实现谓词treeToListX,List,其中X是给定的有序非空二叉树,List是树节点中元素的有序列表 4 / \ 2 6 / \ / \ 1 3 5 7 是作为谓词树列表的输入给定的有序树。 您的程序必须计算列表[1,2,3,4,5,6,7] 以下是我目前掌握的代码: treeToListX,List:-binaryT

实现谓词treeToListX,List,其中X是给定的有序非空二叉树,List是树节点中元素的有序列表

            4               
           / \
         2     6
        / \   / \ 
       1   3  5  7              
是作为谓词树列表的输入给定的有序树。 您的程序必须计算列表[1,2,3,4,5,6,7]

以下是我目前掌握的代码:

treeToListX,List:-binaryTreeX,convertX,List

转换treeElement,void,void,List:-List=[Element]

如果X是给定的非空树,则帮助谓词convertX,List为true,并且List是该树的有序列表表示形式

但是我不知道如何写这个问题的递归部分

转换treeRoot、左、右、列表:-


有人能帮我完成这部分吗?

您从未在Prolog中明确说明数据结构的外观,但我可以推断您基本上有两种树节点:

树元素,左,右 无效的 要处理任何递归数据结构,需要编写一个递归谓词。通常但并非总是需要针对每种元素的子句。在Haskell中,这一点更为明确,因为您必须定义类型及其构造函数,但是您可以在这里应用相同的推理。因此,convert/2谓词将为每种元素都有一个子句:

convert(void, ...) :- ...
convert(tree(Element, Left, Right), ...) :- ...
你可以马上看到第一条非常简单:

convert(void, []).
第二条是事情变得更有趣的地方。关键是递归地将convert/2应用于左侧和右侧的子树,然后需要对现有的元素执行一些操作:

convert(tree(Element, Left, Right), Rest) :-
    convert(Left, LeftList),
    convert(Right, RightList),
    append(LeftList, [Element|RightList], Rest).
请注意,在追加之前,我将当前元素预先添加到右侧列表中。这是将元素插入到列表中的适当位置,以便按顺序遍历,以获得所需的结果:

?- convert(tree(4, tree(2, tree(1, void, void), tree(3, void, void)),
                   tree(6, tree(5, void, void), tree(7, void, void))), 
           List).
List = [1, 2, 3, 4, 5, 6, 7].

这将为您提供顺序遍历。如果您希望进行预序或后序遍历,您可以将元素放置在另一个位置,例如结果的开头或结尾。

您从未在Prolog中明确说明数据结构的外观,但我可以推断您基本上有两种树节点:

树元素,左,右 无效的 要处理任何递归数据结构,需要编写一个递归谓词。通常但并非总是需要针对每种元素的子句。在Haskell中,这一点更为明确,因为您必须定义类型及其构造函数,但是您可以在这里应用相同的推理。因此,convert/2谓词将为每种元素都有一个子句:

convert(void, ...) :- ...
convert(tree(Element, Left, Right), ...) :- ...
你可以马上看到第一条非常简单:

convert(void, []).
第二条是事情变得更有趣的地方。关键是递归地将convert/2应用于左侧和右侧的子树,然后需要对现有的元素执行一些操作:

convert(tree(Element, Left, Right), Rest) :-
    convert(Left, LeftList),
    convert(Right, RightList),
    append(LeftList, [Element|RightList], Rest).
请注意,在追加之前,我将当前元素预先添加到右侧列表中。这是将元素插入到列表中的适当位置,以便按顺序遍历,以获得所需的结果:

?- convert(tree(4, tree(2, tree(1, void, void), tree(3, void, void)),
                   tree(6, tree(5, void, void), tree(7, void, void))), 
           List).
List = [1, 2, 3, 4, 5, 6, 7].

这将为您提供顺序遍历。如果您希望进行预排序或后排序遍历,您可以将元素放置在另一个位置,例如结果的开头或结尾。

根据问题,您的树有两个数据族:

永恒的空虚;和 一个复合术语,其树/3以值和左右子树作为参数。 我们可以实现类似的谓词。通过定义谓词convert/3,我们可以稍微优化它,其中第一个参数是要转换的树,第二个参数是列表的头,第三个参数是列表的尾

因此,我们可以将谓词定义为:

convert(void, L, L).
convert(tree(V, L, R), H, T2) :-
    convert(L, H, [V|T1]),
    convert(R, T1, T2).
如果我们因此遇到一个空白,那么列表的开始和结束保持不变。如果我们遇到一个treeV,L,R,我们将首先递归地调用convertL,H,[V | T1]。通过将[V | T1]写为tail,我们迫使Prolog在结果中产生V值。然后,尾部T1是第二个子树的convert/3的开始

然后,我们可以根据convert/3定义convert/2:


根据问题,您的树有两个数据族:

永恒的空虚;和 一个复合术语,其树/3以值和左右子树作为参数。 我们可以实现类似的谓词。通过定义谓词convert/3,我们可以稍微优化它,其中第一个参数是要转换的树,第二个参数是列表的头,第三个参数是列表的尾

因此,我们可以将谓词定义为:

convert(void, L, L).
convert(tree(V, L, R), H, T2) :-
    convert(L, H, [V|T1]),
    convert(R, T1, T2).
如果我们因此遇到一个空白,那么列表的开始和结束保持不变。如果我们遇到一个treeV,L,R,我们将首先递归地调用convertL,H,[V | T1]。通过将[V | T1]写为tail,我们迫使Prolog在结果中产生V值。然后,尾部T1是第二个子树的convert/3的开始

我们 然后可以根据convert/3定义convert/2:


在Java/C++/….这样的语言中,您将如何做到这一点?在Java/C++/….这样的语言中,您将如何做到这一点?感谢您的清晰解释!这对我来说是一个很有帮助的回答。@Allenl我很高兴我能帮上忙!享受序言!顺便说一下,我有一个关于递归部分的问题。我们是不是先遍历左边的子树,然后把它们都放到一个列表中,然后对右边的子树做同样的事情,最后把它们附加在一起?我说得对吗?@AllenLi是的,那就是那里发生的事情。谢谢你的清楚解释!这对我来说是一个很有帮助的回答。@Allenl我很高兴我能帮上忙!享受序言!顺便说一下,我有一个关于递归部分的问题。我们是不是先遍历左边的子树,然后把它们都放到一个列表中,然后对右边的子树做同样的事情,最后把它们附加在一起?我说得对吗?@AllenLi是的,这就是那里正在发生的事情。谢谢你的回答!谢谢你的回答!