List 二叉树的宽度优先-使用半文本表示法

List 二叉树的宽度优先-使用半文本表示法,list,prolog,dcg,dcg-semicontext,List,Prolog,Dcg,Dcg Semicontext,我想计算列表是二叉树上的bfs顺序。此外,它应该在第二个侧面工作——对于列表,它可以找到树。 你能给我一些提示吗,到目前为止我已经用过类似的东西,当然它不起作用 bfs(nil) --> []. bfs(t(X, L, R)), [X] --> bfs(L), bfs(R). 这就是如何使用(不使用半导体)和累加器来完成的: tree_bfss(T, Xs) :- phrase(bfs1([T]), Xs). bfs1([]) --> [].

我想计算列表是二叉树上的bfs顺序。此外,它应该在第二个侧面工作——对于列表,它可以找到树。
你能给我一些提示吗,到目前为止我已经用过类似的东西,当然它不起作用

bfs(nil) --> [].
bfs(t(X, L, R)), [X] --> bfs(L), bfs(R).

这就是如何使用(不使用半导体)和累加器来完成的:

tree_bfss(T, Xs) :-
   phrase(bfs1([T]), Xs).

bfs1([]) --> [].                    % done if level is empty           
bfs1([X|Xs]) -->
   step_(X, [], Ts),                % single step
   bfs0_(Xs, Ts).                   % process items in this level

bfs0_([], Ts) -->               
   bfs1(Ts).                        % process next level
bfs0_([X|Xs], Ts0) -->
   step_(X, Ts0, Ts),               % single step
   bfs0_(Xs, Ts).                   % continue with this level

step_(nil, Ts, Ts) --> [].
step_(t(L,M,R), Ts, [R,L|Ts]) -->   % push R and L to the next level
   [M].                             % take care of M right now
使用SICStus Prolog 4.3.2的示例查询:

| ?- tree_bfss(t(t(nil,1,t(nil,2,nil)),3,t(nil,4,nil)), Xs).
Xs = [3,4,1,2] ? ;
no
往另一个方向走怎么样

| ?- tree_bfss(T, [3,4,1,2]).
T = t(t(t(t(nil,2,nil),1,nil),4,nil),3,nil) ? ;
T = t(t(t(nil,1,t(nil,2,nil)),4,nil),3,nil) ? ;
T = t(t(nil,4,t(t(nil,2,nil),1,nil)),3,nil) ? ;
T = t(t(nil,4,t(nil,1,t(nil,2,nil))),3,nil) ? ;
T = t(t(t(nil,2,nil),4,t(nil,1,nil)),3,nil) ? ;
T = t(nil,3,t(t(t(nil,2,nil),1,nil),4,nil)) ? ;
T = t(nil,3,t(t(nil,1,t(nil,2,nil)),4,nil)) ? ;
T = t(nil,3,t(nil,4,t(t(nil,2,nil),1,nil))) ? ;
T = t(nil,3,t(nil,4,t(nil,1,t(nil,2,nil)))) ? ;
T = t(nil,3,t(t(nil,2,nil),4,t(nil,1,nil))) ? ;
T = t(t(nil,1,nil),3,t(t(nil,2,nil),4,nil)) ? ;
T = t(t(nil,1,nil),3,t(nil,4,t(nil,2,nil))) ? ;
T = t(t(t(nil,2,nil),1,nil),3,t(nil,4,nil)) ? ;
T = t(t(nil,1,t(nil,2,nil)),3,t(nil,4,nil)) ? ;
no
编辑 有用的意见建议澄清清单项目的顺序:

  • 上述代码不保证每个树级别内的任何特定顺序

  • 它确实确保第i级的所有项目出现在第(i+1)级的所有项目之前


(这使得实现稍微简单了一些。)

看起来@repeat想出了一个不错的DCG解决方案。与此同时,我提出了一个“传统”的基于队列的解决方案,它是非DCG的:

bfs_tree_list(nil, []).
bfs_tree_list(Tree, List) :-
    bfs_q_list([Tree], List).

bfs_q_list([], []).
bfs_q_list([t(X,L,R)|Qs], [X|Xs]) :-
    enqueue(L, Qs, Q1),
    enqueue(R, Q1, Q2),
    bfs_q_list(Q2, Xs).

% "naive" enqueue using append
enqueue(nil, Q, Q).
enqueue(t(X,L,R), Q1, Q2) :- append(Q1, [t(X,L,R)], Q2).
这遵循我在评论中提供的链接中显示的方法。它还遵循严格的从左到右的遍历顺序,我相信这在二叉树遍历中是常规的。它比链接中的要简单一些,因为它们是用于更一般的图而不是二叉树。对上述情况的描述很简单:

  • 从队列中的顶层开始
  • 对于队列中的每个元素(直到队列为空) (a) 退出队列并接受当前节点值
    (b) 将左侧和右侧节点排队
  • 上述代码生成:

    | ?- bfs_tree_list(t(3,t(1,nil,t(2,nil,nil)),t(4,nil,nil)), L).
    
    L = [3,1,4,2]
    
    (1 ms) yes
    
    以及:


    这里有一个修订版,它使用了差异列表,而不是
    append/3

    bfs_tree_list(nil, []).
    bfs_tree_list(Tree, List) :-
        bfs_q_list([Tree|T], T, List).
    
    bfs_q_list(Q, T, []) :- Q == T, !.
    bfs_q_list([t(X,L,R)|Qs], T, [X|Xs]) :-
        [t(X,L,R)|Qs] \== T,
        enqueue(L, T1, T),
        enqueue(R, NewT, T1),
        bfs_q_list(Qs, NewT, Xs).
    
    enqueue(nil, Q, Q).
    enqueue(t(X,L,R), T, [t(X,L,R)|T]).
    

    你试过在谷歌上搜索“Prolog BFS”吗?你会得到的。这将比做DFS更复杂。一种方法是使用队列,其他语言在开发BFS方法时也使用队列。搜索列表中还有一个有趣的演示,它使用了其他技术。是的,我检查过了。尽管如此,请记住我的情况是特殊的-它是二叉树。你是指封闭列表还是开放列表?我是指如果你单击我的链接,在搜索结果列表中。:)事实上,处理二叉树并不会改变BFS技术本身。它只是改变了遍历的一些次要细节。事实上,这可能只是所示方法的特殊化。在搜索过程中有很多用于PROlog的BFS链接,我想至少其中一个可以专门做二叉树,但是一定有一些东西可以让你在那里找到更多的东西。鲍里斯。它让我感觉更自然:(1)它类似于图形表示,(2)命名
    t/3
    的参数(稍微)更容易:
    L
    eft,
    M
    iddle,
    R
    light,我认为将二叉树节点的属性表示为“value,left,right”更常见。你的代码真的产生
    [3,4,1,2]
    是为了那棵树吗?我认为正确的BFS遍历应该是
    [3,1,4,2]
    。可能将
    步骤(t(L,M,R),Ts[R,L|Ts])
    更改为
    步骤(t(L,M,R),Ts[L,R|Ts])
    )@潜伏者。是的。我认为项目的顺序(在一个级别内)是未指定的,不一定是从左到右。。。起初,我有你提议的命令。但是代码变得简单了一点(通过使用累加器而不是第二个差异列表)。另一种选择是,可以使用
    reverse/2
    如下:
    bfs0([],Ts0)-->reverse(Ts0,Ts),bfs1(Ts)。
    但是,我认为这不是必需的。你能告诉我如何实现开放/差异列表排队吗?@HaskellFun我在我的答案中添加了这个版本。非常感谢@重复一遍!我认为我做得很好,因为它是“我发现正确地删除一个无用的选择点并不容易。”再次感谢您的建议。我在用这些术语思考一些事情。:)
    bfs_tree_list(nil, []).
    bfs_tree_list(Tree, List) :-
        bfs_q_list([Tree|T], T, List).
    
    bfs_q_list(Q, T, []) :- Q == T, !.
    bfs_q_list([t(X,L,R)|Qs], T, [X|Xs]) :-
        [t(X,L,R)|Qs] \== T,
        enqueue(L, T1, T),
        enqueue(R, NewT, T1),
        bfs_q_list(Qs, NewT, Xs).
    
    enqueue(nil, Q, Q).
    enqueue(t(X,L,R), T, [t(X,L,R)|T]).