计算二叉树序言中的出现次数
Counting occurrences in binary tree prolog
我想实现一个代码来获取整个树中某个数字的出现次数,例如:
numberOfOccurrences(7, bt(6, bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
bt(8, bt(7, nil, nil),
bt(9, nil, nil))), N).
N = 1;
我该怎么做?
你试过定义
numberOfOccurrences(7, bt(6, bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
bt(8, bt(7, nil, nil),
bt(9, nil, nil))), 1).
?你试过定义
numberOfOccurrences(7, bt(6, bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
bt(8, bt(7, nil, nil),
bt(9, nil, nil))), N) :-
N = 1.
?你试过定义
numberOfOccurrences(7, T, N) :-
T = bt(6, bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
bt(8, bt(7, nil, nil),
bt(9, nil, nil))),
N = 1.
?或者甚至
numberOfOccurrences(7, T, N) :-
T = bt(6, TL, TR),
TL = bt(2, bt(1, nil, nil), %%
bt(3, nil, nil)),
TR = bt(8, bt(7, nil, nil), %%
bt(9, nil, nil)),
N = 1.
?您是否也尝试过定义
numberOfOccurrences(7, T, N) :-
T = bt(6, TL, TR),
N1 = 0, %%
TL = bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
NL = 0, %%
TR = bt(8, bt(7, nil, nil),
bt(9, nil, nil)),
NR = 1, %%
N is N1 + NL + NR. %%
?
不也是这样吗
numberOfOccurrences(7, T, N) :-
T = bt(6, TL, TR),
N1 = 0,
TL = bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
numberOfOccurrences(7, TL, NL), %%
NL = 0,
TR = bt(8, bt(7, nil, nil),
bt(9, nil, nil)),
numberOfOccurrences(7, TR, NR), %%
NR = 1,
N is N1 + NL + NR.
?而且还只是
numberOfOccurrences(7, T, N) :-
T = bt(6, TL, TR),
N1 = 0,
%%
numberOfOccurrences(7, TL, NL),
%%
numberOfOccurrences(7, TR, NR),
%%
N is N1 + NL + NR.
?您是否尝试过进一步概括它,删除最后的人为具体值,也用逻辑变量替换它们,
numberOfOccurrences( X, T, N) :- %%
T = bt( Y, TL, TR), %%
count_one_possible_occurrence( X, Y, N1),
numberOfOccurrences( X, TL, NL), %%
numberOfOccurrences( X, TR, NR), %%
N is N1 + NL + NR.
?你能继续这个思路吗?
你应该试着把大问题分解成多个小问题。所以首先:对树进行操作很复杂,列表更容易处理:
treeToList(Tree, List) :-
% I use an accumulator, starting with an empty list.
treeToList(Tree, [], List).
% The bottom is reached: The accumulated elements are the result.
treeToList(nil, Accu, Accu).
treeToList(bt(E, Left, Right), Accu0, List) :-
Accu1 = [E|Accu0], % prepend the accumulator with the current element
treeToList(Left, Accu1, Accu2), % prepend elements of the left node
treeToList(Right, Accu2, List). % prepend elements of the right node
?- treeToList(bt(6, bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
bt(8, bt(7, nil, nil),
bt(9, nil, nil))), L).
L = [9, 7, 8, 3, 1, 2, 6].
在排序列表中计数比在未排序列表中计数要容易得多。 Prolog 有一个 built-in sort/2 谓词。
?- sort([9, 7, 8, 3, 1, 2, 6], L).
L = [1, 2, 3, 6, 7, 8, 9].
您可以计算相邻值的个数,一步得到剩余的不同值:
removeFromFrontAndCount(_, [], [], N, N).
removeFromFrontAndCount(E, [F|Out], [F|Out], N, N) :-
E \= F.
removeFromFrontAndCount(E, [E|In], Out, N0, N2) :-
N1 is N0 + 1,
removeFromFrontAndCount(E, In, Out, N1, N2).
?- removeFromFrontAndCount(1, [1,1,1,2,3,4], L, 0, N).
L = [2, 3, 4],
N = 3 ;
false.
使用那个助手是谓词 countAdjacent/3:
countAdjacent(List0, E, N) :-
[E0|List1] = List0,
removeFromFrontAndCount(E0, List1, List2, 1, CountE),
( % a semicolon is an either-or operator
E = E0, N = CountE;
countAdjacent(List2, E, N)
).
?- countAdjacent([1,1,1,2,2,3], E, N).
E = 1, N = 3 ;
E = 2, N = 2 ;
E = 3, N = 1 ;
false.
并结合一切:
numberOfOccurrences(E, Tree, N) :-
treeToList(Tree, List),
sort(List, SortedList),
countAdjacent(SortedList, E, N).
?- numberOfOccurrences(E, bt(6, bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
bt(8, bt(7, nil, nil),
bt(9, nil, nil))), L).
E = 1, L = 1 ;
E = 2, L = 1 ;
E = 3, L = 1 ;
E = 6, L = 1 ;
E = 7, L = 1 ;
E = 8, L = 1 ;
E = 9, L = 1 ;
false.
完整代码:
numberOfOccurrences(E, Tree, N) :-
treeToList(Tree, List),
sort(List, SortedList),
countAdjacent(SortedList, E, N).
treeToList(Tree, List) :-
treeToList(Tree, [], List).
treeToList(nil, Accu, Accu).
treeToList(bt(E, Left, Right), Accu0, List) :-
treeToList(Left, [E|Accu0], Accu1),
treeToList(Right, Accu1, List).
countAdjacent(List0, E, N) :-
[E0|List1] = List0,
removeFromFrontAndCount(E0, List1, List2, 1, CountE),
(
E = E0, N = CountE;
countAdjacent(List2, E, N)
).
removeFromFrontAndCount(_, [], [], N, N).
removeFromFrontAndCount(E, [F|Out], [F|Out], N, N) :-
E \= F.
removeFromFrontAndCount(E, [E|In], Out, N0, N2) :-
N1 is N0 + 1,
removeFromFrontAndCount(E, In, Out, N1, N2).
我想实现一个代码来获取整个树中某个数字的出现次数,例如:
numberOfOccurrences(7, bt(6, bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
bt(8, bt(7, nil, nil),
bt(9, nil, nil))), N).
N = 1;
我该怎么做?
你试过定义
numberOfOccurrences(7, bt(6, bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
bt(8, bt(7, nil, nil),
bt(9, nil, nil))), 1).
?你试过定义
numberOfOccurrences(7, bt(6, bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
bt(8, bt(7, nil, nil),
bt(9, nil, nil))), N) :-
N = 1.
?你试过定义
numberOfOccurrences(7, T, N) :-
T = bt(6, bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
bt(8, bt(7, nil, nil),
bt(9, nil, nil))),
N = 1.
?或者甚至
numberOfOccurrences(7, T, N) :-
T = bt(6, TL, TR),
TL = bt(2, bt(1, nil, nil), %%
bt(3, nil, nil)),
TR = bt(8, bt(7, nil, nil), %%
bt(9, nil, nil)),
N = 1.
?您是否也尝试过定义
numberOfOccurrences(7, T, N) :-
T = bt(6, TL, TR),
N1 = 0, %%
TL = bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
NL = 0, %%
TR = bt(8, bt(7, nil, nil),
bt(9, nil, nil)),
NR = 1, %%
N is N1 + NL + NR. %%
?
不也是这样吗numberOfOccurrences(7, T, N) :-
T = bt(6, TL, TR),
N1 = 0,
TL = bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
numberOfOccurrences(7, TL, NL), %%
NL = 0,
TR = bt(8, bt(7, nil, nil),
bt(9, nil, nil)),
numberOfOccurrences(7, TR, NR), %%
NR = 1,
N is N1 + NL + NR.
?而且还只是
numberOfOccurrences(7, T, N) :-
T = bt(6, TL, TR),
N1 = 0,
%%
numberOfOccurrences(7, TL, NL),
%%
numberOfOccurrences(7, TR, NR),
%%
N is N1 + NL + NR.
?您是否尝试过进一步概括它,删除最后的人为具体值,也用逻辑变量替换它们,
numberOfOccurrences( X, T, N) :- %%
T = bt( Y, TL, TR), %%
count_one_possible_occurrence( X, Y, N1),
numberOfOccurrences( X, TL, NL), %%
numberOfOccurrences( X, TR, NR), %%
N is N1 + NL + NR.
?你能继续这个思路吗?
你应该试着把大问题分解成多个小问题。所以首先:对树进行操作很复杂,列表更容易处理:
treeToList(Tree, List) :-
% I use an accumulator, starting with an empty list.
treeToList(Tree, [], List).
% The bottom is reached: The accumulated elements are the result.
treeToList(nil, Accu, Accu).
treeToList(bt(E, Left, Right), Accu0, List) :-
Accu1 = [E|Accu0], % prepend the accumulator with the current element
treeToList(Left, Accu1, Accu2), % prepend elements of the left node
treeToList(Right, Accu2, List). % prepend elements of the right node
?- treeToList(bt(6, bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
bt(8, bt(7, nil, nil),
bt(9, nil, nil))), L).
L = [9, 7, 8, 3, 1, 2, 6].
在排序列表中计数比在未排序列表中计数要容易得多。 Prolog 有一个 built-in sort/2 谓词。
?- sort([9, 7, 8, 3, 1, 2, 6], L).
L = [1, 2, 3, 6, 7, 8, 9].
您可以计算相邻值的个数,一步得到剩余的不同值:
removeFromFrontAndCount(_, [], [], N, N).
removeFromFrontAndCount(E, [F|Out], [F|Out], N, N) :-
E \= F.
removeFromFrontAndCount(E, [E|In], Out, N0, N2) :-
N1 is N0 + 1,
removeFromFrontAndCount(E, In, Out, N1, N2).
?- removeFromFrontAndCount(1, [1,1,1,2,3,4], L, 0, N).
L = [2, 3, 4],
N = 3 ;
false.
使用那个助手是谓词 countAdjacent/3:
countAdjacent(List0, E, N) :-
[E0|List1] = List0,
removeFromFrontAndCount(E0, List1, List2, 1, CountE),
( % a semicolon is an either-or operator
E = E0, N = CountE;
countAdjacent(List2, E, N)
).
?- countAdjacent([1,1,1,2,2,3], E, N).
E = 1, N = 3 ;
E = 2, N = 2 ;
E = 3, N = 1 ;
false.
并结合一切:
numberOfOccurrences(E, Tree, N) :-
treeToList(Tree, List),
sort(List, SortedList),
countAdjacent(SortedList, E, N).
?- numberOfOccurrences(E, bt(6, bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
bt(8, bt(7, nil, nil),
bt(9, nil, nil))), L).
E = 1, L = 1 ;
E = 2, L = 1 ;
E = 3, L = 1 ;
E = 6, L = 1 ;
E = 7, L = 1 ;
E = 8, L = 1 ;
E = 9, L = 1 ;
false.
完整代码:
numberOfOccurrences(E, Tree, N) :-
treeToList(Tree, List),
sort(List, SortedList),
countAdjacent(SortedList, E, N).
treeToList(Tree, List) :-
treeToList(Tree, [], List).
treeToList(nil, Accu, Accu).
treeToList(bt(E, Left, Right), Accu0, List) :-
treeToList(Left, [E|Accu0], Accu1),
treeToList(Right, Accu1, List).
countAdjacent(List0, E, N) :-
[E0|List1] = List0,
removeFromFrontAndCount(E0, List1, List2, 1, CountE),
(
E = E0, N = CountE;
countAdjacent(List2, E, N)
).
removeFromFrontAndCount(_, [], [], N, N).
removeFromFrontAndCount(E, [F|Out], [F|Out], N, N) :-
E \= F.
removeFromFrontAndCount(E, [E|In], Out, N0, N2) :-
N1 is N0 + 1,
removeFromFrontAndCount(E, In, Out, N1, N2).