prolog - bst树列表

时间:2016-05-21 13:23:37

标签: prolog dcg

我正在练习dcg技术,但我遇到了问题。我将实现转换BST树到列表(每个可能)和反向侧 - 列表ot bst(每个可能)。 (列表表示实际设置) 然而,
这个语法应该没问题,但它会产生非常多的重复。我知道原因(nil),但我不能处理它。

 bstToList(nil) --> [].
    bstToList(t(Root, L, R)) --> [Root], bstToList(L), bstToList(R).
    bstToList(t(Root, L, R)) --> [Root], bstToList(R), bstToList(L).
    bstToList(t(Root, L, R)) -->  bstToList(R), [Root], bstToList(L).
    bstToList(t(Root, L, R)) -->  bstToList(L), [Root], bstToList(R).
    bstToList(t(Root, L, R)) --> bstToList(L), bstToList(R), [Root].
    bstToList(t(Root, L, R)) --> bstToList(R), bstToList(L), [Root].

你能帮帮我吗?

1 个答案:

答案 0 :(得分:2)

你如何实现它的问题是你在每个遍历步骤中混合每个遍历方法。换句话说,在每个遍历步骤中,您的谓词将探索每种遍历方法。

你需要在更高的层次上突破它们:

bst_to_list(BST, Ls) -->
    bst_to_list_pre_LR(BST, Ls, _) |
    bst_to_list_pre_RL(BST, Ls, _) |
    bst_to_list_in_LR(BST, Ls, _) |
    bst_to_list_in_RL(BST, Ls, _) |
    bst_to_list_post_LR(BST, Ls, _) |
    bst_to_list_post_RL(BST, Ls, _).

然后单独实现每种类型:

% Pre-order, left-to-right
bst_to_list_pre_LR(nil, Es, Es) --> [].
bst_to_list_pre_LR(t(Root, L, R), [_|Es0], Es) -->
    [Root],
    bst_to_list_pre_LR(L, Es0, Es1),
    bst_to_list_pre_LR(R, Es1, Es).

% Pre-order right-to-left
bst_to_list_pre_RL(nil, Es, Es) --> [].
bst_to_list_pre_RL(t(Root, L, R), [_|Es0], Es) -->
    [Root],
    bst_to_list_pre_RL(R, Es0, Es1),
    bst_to_list_pre_RL(L, Es1, Es).

... % Etc...

另外,请仔细阅读@ mat对您先前问题Prolog, reconstruct BST trees from inorder list的回答,因为这里提供了有用的技术,可以为每种情况提供更强大的解决方案。我在上面的代码中加入了这种技术。

请注意,您仍然可能会出现重复,因为某些树在以不同方式遍历时会产生相同的结果。

<小时/> 根据评论,似乎寻求一种解决方案来定义BST和节点列表之间的关系,使得BST中的顺序可以是任意的。由于订购可能是任何东西,它不适合DCG。这是一个可能的非DCG解决方案:

bst_list_all(BST, L) :-
    tree_list_bound(BST, L, _),
    bst_list_all_(BST, L).

bst_list_all_(nil, []).
bst_list_all_(t(Root, L, R), Es) :-
    select(Root, Es, Es1),
    append(Ls, Rs, Es1),
    bst_list_all_(L, Ls),
    bst_list_all_(R, Rs).

tree_list_bound(nil, [], []).
tree_list_bound(t(_, L, R), [_|Es0], Es2) :-
    tree_list_bound(L, Es0, Es1),
    tree_list_bound(R, Es1, Es2).
tree_list_bound(t(_, L, R), [_|Es0], Es2) :-
    Es0 = [_|_],
    tree_list_bound(R, Es0, Es1),
    tree_list_bound(L, Es1, Es2).

谓词tree_list_bound为解决方案建立了一个有界框架,以避免终止问题。它“感觉”这个解决方案可能会被浓缩,但我还没有找到办法。但是,它确实提供了解决所揭示问题的方法,而没有产生重复的解决方案。

?- bst_list_all(t(1,nil,t(2,t(3,nil,nil),nil)), L).
L = [1, 2, 3] ;
L = [1, 3, 2] ;
L = [2, 1, 3] ;
L = [3, 1, 2] ;
L = [2, 3, 1] ;
L = [3, 2, 1] ;
false.

?- bst_list_all(BST, [1,2,3]).
BST = t(1, t(2, t(3, nil, nil), nil), nil) ;
BST = t(1, t(3, t(2, nil, nil), nil), nil) ;
BST = t(2, t(1, t(3, nil, nil), nil), nil) ;
BST = t(2, t(3, t(1, nil, nil), nil), nil) ;
BST = t(3, t(1, t(2, nil, nil), nil), nil) ;
BST = t(3, t(2, t(1, nil, nil), nil), nil) ;
BST = t(1, t(2, nil, t(3, nil, nil)), nil) ;
BST = t(1, t(3, nil, t(2, nil, nil)), nil) ;
BST = t(2, t(1, nil, t(3, nil, nil)), nil) ;
BST = t(2, t(3, nil, t(1, nil, nil)), nil) ;
BST = t(3, t(1, nil, t(2, nil, nil)), nil) ;
BST = t(3, t(2, nil, t(1, nil, nil)), nil) ;
BST = t(1, nil, t(2, t(3, nil, nil), nil)) ;
BST = t(1, nil, t(3, t(2, nil, nil), nil)) ;
BST = t(2, nil, t(1, t(3, nil, nil), nil)) ;
BST = t(2, nil, t(3, t(1, nil, nil), nil)) ;
BST = t(3, nil, t(1, t(2, nil, nil), nil)) ;
BST = t(3, nil, t(2, t(1, nil, nil), nil)) ;
BST = t(1, nil, t(2, nil, t(3, nil, nil))) ;
BST = t(1, nil, t(3, nil, t(2, nil, nil))) ;
BST = t(2, nil, t(1, nil, t(3, nil, nil))) ;
BST = t(2, nil, t(3, nil, t(1, nil, nil))) ;
BST = t(3, nil, t(1, nil, t(2, nil, nil))) ;
BST = t(3, nil, t(2, nil, t(1, nil, nil))) ;
false.

?-